std :: make_pair类型扣除

reg*_*psj 4 c++ templates stl c++11

我遇到了一些奇怪的事情,我想要解释一下.以下代码片段提供了一个简单的类模板type和两个operator<<s:一个用于特化type,一个用于特std::pairtype.

#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
}
Run Code Online (Sandbox Code Playgroud)

main函数提供了特化和该特化的两个变量.将变量显示为a有两种变体std::pair.第一个失败是因为std::make_pair似乎const从变量中剥离了说明符,而变量又与第二个的签名不匹配operator<<:std::pair<T const, T const>.但是,构建std::pair专业化(第二std::coutmain)以及从for中删除const规范,即.Toperator<<std::pairstd::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)
     ^
    
    Run Code Online (Sandbox Code Playgroud)
  • clang 3.5(删除了系统头中的不可行功能)

    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)
    
    Run Code Online (Sandbox Code Playgroud)

所以,这里的问题:我应该到指定operator<<std::pairT,而不是T const?难道这不会影响我与任何功能用户建立的合同,即T const我基本上承诺T只能以非变异方式使用吗?

Bar*_*rry 8

第一个失败是因为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);
Run Code Online (Sandbox Code Playgroud)

返回:pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y)); 在那里V1,并V2决定如下:设Uidecay_t<Ti>每个Ti.然后,每个ViX&,如果Ui等号reference_wrapper<X>,否则ViUi.

编译器完全正确拒绝你的代码 - 你添加了一个流操作符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;
}
Run Code Online (Sandbox Code Playgroud)

已经把它pair引用到了const,它不像你可以修改它的内容.