Это не ошибка, MSVC компилирует ваш код, потому что имеет расширение, которое позволяет привязывать временный объект (Rvalue) к неконстантной ссылке Lvalue.
Ниже код компилируется с MSVC:
void foo(int& i) {}
foo(20); // you are passing Rvalue and it is bound to Lvalue reference
Выше код не компилируется под G ++ или CLang, когда вы добавляете const
, чтобы сделать ссылку на
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);
вы передаете временную объективность (Rvalue) в exchange
, который принимает первый аргумент по ссылке на неконстантное Lvalue. Это причина того, что G ++ отказывается от этого кода. Если вы хотите скомпилировать его, вы можете явно создать объект Lvalue класса proxy и передать его:
bool kill(std::size_t index)
{
std::vector<bool>::reference proxyForBit = lifeTimes[index];
return std::exchange(proxyForBit, false);
}