std :: vector <bool> ::带有std :: exchange的引用

时间:2018-11-06 23:35:48

标签: gcc visual-c++ stl clang c++14

是否存在std :: exchange无法在std :: vector :: reference上运行的技术原因,还是GCC和Clang实现中的错误? With MSVC it compiles fine

我有这样的设置(最小示例)

struct Manager
{
  std::vector<bool> lifeTimes;

  //Should return the state before trying to kill it
  bool kill(std::size_t index)
  {
    return std::exchange(lifeTimes[index], false);
  }
};

std :: exchange将使它成为一个非常不错的班轮,但GCC抱怨:

  

错误:无法将类型'std :: _ Bit_reference&'的非常量左值引用绑定到类型为'std :: vector :: reference'的右值{aka'std :: _ Bit_reference'}

因此,它似乎抱怨false since only the second parameter is an rvalue

1 个答案:

答案 0 :(得分:2)

这不是错误,MSVC会编译您的代码,因为它具有扩展功能,可以将临时对象(Rvalue)绑定到非常量Lvalue引用。

以下代码使用MSVC编译:

void foo(int& i) {}
foo(20); // you are passing Rvalue and it is bound to Lvalue reference

当您添加const来引用时,以上代码无法在G ++或CLang下编译 const Lvalue,它可以正常工作:

void foo(const int&){}
foo(20); // you can bind Rvalue to const Lvalue reference

关于向量的几句话。 operator[]代表vector<T>,其中T是除布尔值以外的所有类型,返回T&

T& vector<T>::operator[](index) // where T is not bool

对于bool向量类模板具有特殊性。存储bool的值以保留一位空间,因为您不能为一位使用地址运算符,vector<bool>::operator[](index)无法返回引用。 vector<bool>具有内部的 proxy 类,该类可操纵位(将该类称为 reference )。

vector<bool>::reference vector<bool>::operator[](index)
              ^^^^^^^^^  
您看到的

proxy 对象是按值传递的。 因此,当您致电

return std::exchange(lifeTimes[index], false);

您正在将临时对象(Rvalue)传递给exchange,后者通过引用非常量Lvalue来获取第一个参数。这就是G ++丢弃此代码的原因。如果要编译它,则可以显式创建 proxy 类的Lvalue对象并将其传递:

  bool kill(std::size_t index)
  {
      std::vector<bool>::reference proxyForBit = lifeTimes[index];
    return std::exchange(proxyForBit, false);
  }