std :: make_pair类型推导 [英] std::make_pair type deduction

查看:146
本文介绍了std :: make_pair类型推导的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一些我想解释的奇怪的事情。以下代码段提供了一个简单的类模板 type 和两个 operator<< s:一个用于 type 和一个 std :: pair 类型为 type 的专业。

I came across some odd thing I would like to have an explanation for. The following code snippet provides a simple class template type and two operator<<s: one for specializations of type and one for a std::pair of type specializations.

#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
}

主程序函数提供一个专业化和该专业化的两个变量。有两种将变量显示为 std :: pair 的变体。第一个失败,因为 std :: make_pair 似乎从变量中删除了 const 说明符,而后者却没有匹配第二个运算符<<的签名: std :: pair< T const,T const> 。但是,构造一个 std :: pair 专业化( main中的第二个 std :: cout )的作用以及从 T const 规范> operator<< for std :: pair ,即 std :: pair< T,T>

The main function provides a specialization and two variables of that specialization. There are two variants for displaying the variables as a std::pair. 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>. However, constructing a std::pair specialization (second std::cout line in main) works as well as removing the const specification for T from operator<< for std::pair, i.e. std::pair<T, T>.

编译器消息::


  • gcc 4.9.2

  • 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(已删除系统标头中的无效功能)

  • clang 3.5 (non-viable functions from system headers removed)

    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 我基本上承诺使用 T 仅以非变异方式提供?

    so, here's the question: am I supposed to specify an operator<< taking a std::pair of T instead of T const? Isn't that watering down the contract I'm setting up with any user of the functionality, i.e. with T const I basically promise to use T only in non-mutating ways?

    推荐答案


    第一个失败的原因是 std :: make_pair 似乎从变量中删除了const说明符,这反过来又与第二个 operator<<的签名不匹配: std :: pair< T const,T const>

    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 & 限定词:

    That is correct. make_pair is a function template that relies on std::decay to explicitly drop const, volatile, and & qualifiers:


    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> c $ c> Ti 。然后,如果 Ui 等于<$,则每个 Vi X& c $ c> reference_wrapper< X> ,否则 Vi Ui

    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。没什么问题。

    The compiler is completely correct to reject your code - you added a stream operator for pair<const T, const T>, but are trying to stream a pair<T, T>. The solution is to just remove the extra const requirement in your stream operator. Nothing in that function requires that the pair consist of const types - just that the types themselves are streamable, which is independent of their constness. There is nothing wrong with this:

    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 (按引用引用常量),就好像您无法始终修改其内容一样。

    You're already taking the pair by reference-to-const, it's not like you can modify its contents anyway.

    这篇关于std :: make_pair类型推导的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆