ошибка: невозможно связать неконстантную ссылку lvalue типа 'bool &' с rvalue типа 'bool' - PullRequest
2 голосов
/ 11 апреля 2020

Я создаю свой собственный класс Matrix. Когда дело доходит до функции «at», используемой для изменения значения определенного элемента, у меня есть это.

T & at(unsigned int raw, unsigned int col)
{
    return (_matrix.at(index(raw, col)));
}

, зная, что

std::vector<T>  _matrix;

Это прекрасно работает для всех ожидаемых типов для логических значений. Я не могу выполнить эту операцию.

matrix.at(1, 1) = true;

Что странно, потому что у меня та же реализация, что и у функции std :: vector "at", которая работает с логическими значениями.

Any идеи? Спасибо.

1 Ответ

3 голосов
/ 11 апреля 2020

std::vector<bool> является особенным для всех других std::vector специализаций.

Его .at функция-член не возвращает ссылку на bool, но прокси-объект, который может быть назначен и преобразован в bool. Ни прокси-объект, ни преобразованный bool (который является prvalue) не может быть привязан к bool&, как вы пытаетесь это сделать в операторе return.

Вы должны обработать регистр T = bool особым образом, например, запретив его для вашего класса матрицы или используя std::vector<char> вместо std::vector<bool>, когда ваш T равен bool:

using U = std::conditional_t<std::is_same_v<T, bool>, char, T>;

std::vector<U>  _matrix;

и затем возвращает U& вместо T& везде, куда вы возвращаете ссылки. (Для этого требуется #include<type_traits> и C ++ 17 в этой форме, но его можно адаптировать к C ++ 11.)

или с использованием обертки вокруг bool, такой как

struct A {
    bool b;
};

, который вы сохраняете в векторе вместо bool, так что вы все равно можете правильно возвращать ссылки на элемент bool,

или, если вы собираетесь использовать механизм упакованного хранилища, который различает std::vector<bool> из всех других std::vector специализаций, вы можете вернуть прокси-объект из вашего .at метода и в основном представить тот же особый случай, который std::vector имеет для вашего матричного класса, но тогда вам нужно будет позаботиться о специальном case везде в вашем матричном классе:

decltype(auto) at(unsigned int raw, unsigned int col)
{
    return _matrix.at(index(raw, col));
}

(удаление скобок в операторе возврата важно в этом случае и требует C ++ 14) или

std::vector<T>::reference at(unsigned int raw, unsigned int col)
{
    return _matrix.at(index(raw, col));
}

Это очень неудачно что std::vector<bool> особенный в этом смысле. Узнайте больше об этом, например, в этом вопросе и на странице cppreference.com для std::vector<bool>.

...