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

问题描述 投票:0回答:2

std::exchange 不适用于 std::vector::reference 是否有技术原因,或者是 GCC 和 Clang 实现中的错误? 使用 MSVC 可以很好地编译

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

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”类型的右值(又名“std::_Bit_reference”)

所以它似乎抱怨

false
因为只有第二个参数是右值

gcc visual-c++ stl clang c++14
2个回答
2
投票

这不是一个错误,MSVC 编译您的代码,因为它有一个扩展,可以将临时对象(右值)绑定到非常量左值引用。

下面的代码使用 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
是除 bool 之外的所有类型返回
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);

您将临时对象(右值)传递给

exchange
,它通过引用非常量左值获取第一个参数。这就是 G++ 丢弃这段代码的原因。如果你想编译它,你可以显式创建 proxy 类的 Lvalue 对象并传递它:

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

0
投票

根据已接受答案中的解释,从 C++17 开始,您可以使用

std::array
包装任何临时对象以获取对其的非常量引用:

std::exchange(std::array{lifeTimes[index]}[0], false)
© www.soinside.com 2019 - 2024. All rights reserved.