我遇到了一些奇怪的事情,我想要解释一下。以下代码段提供了一个简单的类模板type
和两个operator<<
s:一个用于type
的特化,另一个用于std::pair
个type
特化。< / p>
#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
中构建std::cout
专门化(第二个main
行)以及从const
删除T
的{{1}}规范是有效的operator<<
,即std::pair
。
编译器消息::
gcc 4.9.2
std::pair<T, T>
clang 3.5(系统标题中删除了不可行的函数)
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)
^
所以,问题是:我是否应该指定一个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<<
std::pair
代替T
?我是否正在与合同的任何用户建立合同,即使用T const
我基本上承诺仅以非变异的方式使用T const
?
答案 0 :(得分:7)
第一个失败是因为
std::make_pair
似乎从变量中删除了const说明符,而变量又与第二个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);
返回:
pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y));
其中V1
和V2
的确定位置如下:对于每个Ui
,decay_t<Ti>
为Ti
。如果Vi
等于X&
,则每个Ui
为reference_wrapper<X>
,否则Vi
为Ui
。
编译器完全正确拒绝您的代码 - 您为pair<const T, const T>
添加了一个流运算符,但正在尝试流式传输pair<T, T>
。解决方案是只删除流运算符中的额外const
要求。该函数中的任何内容都不要求pair
由const
类型组成 - 只是类型本身是可流式的,这与它们的const
无关。这没有错:
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
,但它无论如何都不能修改其内容。