std::make_pair 类型推导
std::make_pair type deduction
我遇到了一些奇怪的事情,我想得到解释。以下代码片段提供了一个简单的 class 模板 type
和两个 operator<<
:一个用于 type
的特化,一个用于 type
的 std::pair
] 专业。
#include <ostream>
#include <utility>
template <typename T>
class type {
public:
T value_;
};
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, type<T> const& a)
{
return os << a.value_;
}
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T const, T const> const& a)
{
return os << a.first << ',' << a.second;
}
#include <iostream>
int
main()
{
using float_type = type<float>;
float_type const a = { 3.14159 };
float_type const b = { 2.71828 };
#if 0
std::cout << std::make_pair(a, b)
<< std::endl;
#else
std::cout << std::pair<float_type const, float_type const>(a, b)
<< std::endl;
#endif
}
main
函数提供了一个专业化和该专业化的两个变量。将变量显示为 std::pair
有两种变体。第一个失败是因为 std::make_pair
似乎从变量中删除了 const
说明符,这又与第二个 operator<<
的签名不匹配:std::pair<T const, T const>
。但是,构建 std::pair
专业化(main
中的第二 std::cout
行)与从 operator<<
中删除 T
的 const
规范一样有效std::pair
,即 std::pair<T, T>
.
编译器消息::
gcc 4.9.2
std_make_pair.cpp: In function 'int main()':
std_make_pair.cpp:52:35: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
std::cout << std::make_pair(a, b) << std::endl;
^
In file included from std_make_pair.cpp:3:0:
/usr/include/c++/4.9.2/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::pair<type<float>, type<float> >]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
clang 3.5(删除了系统 headers 中的 non-viable 功能)
std_make_pair.cpp:52:13: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>')
and 'pair<typename __decay_and_strip<const type<float> &>::__type, typename __decay_and_strip<const
type<float> &>::__type>')
std::cout << std::make_pair(a, b) << std::endl;
~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~
std_make_pair.cpp:30:1: note: candidate template ignored: can't deduce a type for 'T' which would make
'const T' equal 'type<float>'
operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T const, T const> const& a)
所以,问题来了:我是否应该指定 operator<<
取 T
的 std::pair
而不是 T const
?这不是削弱了我与该功能的任何用户建立的合同,即 T const
我基本上承诺仅以 non-mutating 方式使用 T
吗?
The first fails because std::make_pair
seems to strip the const specifier from the variables, which in turn doesn't match with the signature of the second operator<<: std::pair<T const, T const>
没错。 make_pair
是一个函数模板,它依赖于 std::decay
显式删除 const
、volatile
和 &
限定符:
template <class T1, class T2>
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);
Returns: pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));
where V1
and V2
are determined as follows: Let Ui
be decay_t<Ti>
for each Ti
. Then each Vi
is X&
if Ui
equals reference_wrapper<X>
, otherwise Vi
is Ui
.
编译器拒绝您的代码是完全正确的 - 您为 pair<const T, const T>
添加了流运算符,但正在尝试流式传输 pair<T, T>
。解决方案是只删除流运算符中额外的 const
要求。该函数中没有任何内容要求 pair
由 const
类型组成——只是类型本身是可流式的,这与它们的 const
ness 无关。这个没有错:
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T, T> const& a)
{
return os << a.first << ',' << a.second;
}
您已经通过常量引用获取pair
,无论如何您都无法修改其内容。
我遇到了一些奇怪的事情,我想得到解释。以下代码片段提供了一个简单的 class 模板 type
和两个 operator<<
:一个用于 type
的特化,一个用于 type
的 std::pair
] 专业。
#include <ostream>
#include <utility>
template <typename T>
class type {
public:
T value_;
};
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, type<T> const& a)
{
return os << a.value_;
}
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T const, T const> const& a)
{
return os << a.first << ',' << a.second;
}
#include <iostream>
int
main()
{
using float_type = type<float>;
float_type const a = { 3.14159 };
float_type const b = { 2.71828 };
#if 0
std::cout << std::make_pair(a, b)
<< std::endl;
#else
std::cout << std::pair<float_type const, float_type const>(a, b)
<< std::endl;
#endif
}
main
函数提供了一个专业化和该专业化的两个变量。将变量显示为 std::pair
有两种变体。第一个失败是因为 std::make_pair
似乎从变量中删除了 const
说明符,这又与第二个 operator<<
的签名不匹配:std::pair<T const, T const>
。但是,构建 std::pair
专业化(main
中的第二 std::cout
行)与从 operator<<
中删除 T
的 const
规范一样有效std::pair
,即 std::pair<T, T>
.
编译器消息::
gcc 4.9.2
std_make_pair.cpp: In function 'int main()': std_make_pair.cpp:52:35: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&' std::cout << std::make_pair(a, b) << std::endl; ^ In file included from std_make_pair.cpp:3:0: /usr/include/c++/4.9.2/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::pair<type<float>, type<float> >]' operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) ^
clang 3.5(删除了系统 headers 中的 non-viable 功能)
std_make_pair.cpp:52:13: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'pair<typename __decay_and_strip<const type<float> &>::__type, typename __decay_and_strip<const type<float> &>::__type>') std::cout << std::make_pair(a, b) << std::endl; ~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~ std_make_pair.cpp:30:1: note: candidate template ignored: can't deduce a type for 'T' which would make 'const T' equal 'type<float>' operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T const, T const> const& a)
所以,问题来了:我是否应该指定 operator<<
取 T
的 std::pair
而不是 T const
?这不是削弱了我与该功能的任何用户建立的合同,即 T const
我基本上承诺仅以 non-mutating 方式使用 T
吗?
The first fails because
std::make_pair
seems to strip the const specifier from the variables, which in turn doesn't match with the signature of the secondoperator<<: std::pair<T const, T const>
没错。 make_pair
是一个函数模板,它依赖于 std::decay
显式删除 const
、volatile
和 &
限定符:
template <class T1, class T2> constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);
Returns:
pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));
whereV1
andV2
are determined as follows: LetUi
bedecay_t<Ti>
for eachTi
. Then eachVi
isX&
ifUi
equalsreference_wrapper<X>
, otherwiseVi
isUi
.
编译器拒绝您的代码是完全正确的 - 您为 pair<const T, const T>
添加了流运算符,但正在尝试流式传输 pair<T, T>
。解决方案是只删除流运算符中额外的 const
要求。该函数中没有任何内容要求 pair
由 const
类型组成——只是类型本身是可流式的,这与它们的 const
ness 无关。这个没有错:
template <typename CTy, typename CTr, typename T>
std::basic_ostream<CTy,CTr>&
operator<<(std::basic_ostream<CTy,CTr>& os, std::pair<T, T> const& a)
{
return os << a.first << ',' << a.second;
}
您已经通过常量引用获取pair
,无论如何您都无法修改其内容。