std :: reference_wrapper问题

时间:2015-05-15 15:11:03

标签: c++ c++11 language-lawyer implicit-conversion reference-wrapper

使用以下代码可以清楚地解决问题:

#include <functional>
#include <iostream>
#include <vector>

int main() {
  //std::vector<int> a, b;
  int a = 0, b = 0;
  auto refa = std::ref(a);
  auto refb = std::ref(b);
  std::cout << (refa < refb) << '\n';
  return 0;
}

如果我使用注释的std::vector<int> a, b;而不是int a = 0, b = 0;,则代码不会在GCC 5.1,clang 3.6或MSVC&#13; 13中的任何一个上编译。在我看来,std::reference_wrapper<std::vector<int>>可以隐式转换为std::vector<int>&,这是LessThanComparable,因此它应该是LessThanComparable本身。有人可以向我解释一下吗?

2 个答案:

答案 0 :(得分:20)

问题是std::vector的非成员operator<是一个功能模板:

template< class T, class Alloc >
bool operator<( const vector<T,Alloc>& lhs,
                const vector<T,Alloc>& rhs );

在此处进行模板类型推导时,隐式转换是,[temp.arg.explicit]强调if:

  

将对函数参数执行隐式转换(第4条),以将其转换为类型   相应的函数参数如果参数类型不包含参与的模板参数   在模板参数演绎中。

但在这种情况下,参数类型确实参与演绎。这就是为什么它找不到的原因。如果我们编写了自己的 -template operator<

bool operator<(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
    return true;
}

您的代码将按预期工作。但是,要使用通用的,您必须明确地提取引用:

std::cout << (refa.get() < refb.get()) << '\n';

答案 1 :(得分:0)

你确定吗

std::vector<int> a, b;

正在做它应该做的事情?以此为例

#include <functional>
#include <iostream>
#include <vector>

int main() {
  std::vector<int> a, b;
  //int a = 0, b = 0;
  a.push_back(42);
  a.push_back(6);
  a.push_back(15);
  for (int ii=0; ii<43; ii++) {
    b.push_back(ii);
  }
  auto refa = std::ref(a);
  auto refb = std::ref(b);
  std::cout<<&refa<<std::endl;
  std::cout<<&refb<<std::endl;
  std::cout<<"Contents of vector A"<<std::endl;
  for(auto n : a)
  {
    std::cout<<' '<<n;
  }
  std::cout<<std::endl<<"Contents of vector b: ";
  for (auto n : b){
    std::cout<<' '<<n;
  }
  //std::cout << (refa < refb) << '\n';
  return 0;
}

结果是

0x7fff5fbff0c0
0x7fff5fbff0b8
Contents of vector A
 42 6 15
Contents of vector b:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

最终

std::vector<int> a, b;

创建两个独立的整数向量,称为a和b,两者都没有内容;这不是如何用成员a和b声明单个向量。

int a=0, b=0;

声明两个单独的整数,称为a和b,每个整数的值为0.这两个代码片段声明完全不同的变量,不应互换使用。