Почему const требуется для контейнера

Почему я получаю C2440 для

for(box& b : uset)

Error C2440 'initializing': cannot convert from 'const box' to 'box &'

Error (active) E0433 qualifiers dropped in binding reference of type "box &" to initializer of type "const box"

class box
{
public:
    int i = 1;
    bool operator==(const box& other) const
    {
        return true;
    }
    bool operator!=(const box& other) const
    {
        return !(*this == other);
    }

};

namespace std {

    template<>
    struct hash<box>
    {
        size_t operator()(const box& boxObject) const
        {
            return boxObject.i;
        }
    };
}

int main()
{
    std::unordered_set<box> uset;
    for (box& b : uset)
    {

    }
    return 0;
}

Я сбит с толку, как будто я делаю ссылку на const box, тогда проблема исчезает. Если я поменяю unordered_set на vector, то это не проблема. Я не уверен, что здесь происходит. Может кто-нибудь помочь объяснить это мне. Это относится к ассоциативным контейнерам? Я вижу, что это также происходит с std::set.

Вы не можете изменять элементы в наборах (только вставлять и удалять их). Разыменование итераторов набора дает вам const объекты.

HolyBlackCat 25.03.2019 21:32

@HolyBlackCat Это ответ, а не комментарий (ИМХО).

Jesper Juhl 25.03.2019 21:34

То, что сказал @Holy, верно. Это связано с тем, что мутация элементов может испортить их порядок/хэш.

DeviatioN 25.03.2019 21:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

decltype(*std::unordered_set<box>{}.begin())

дает вам const box&. Вы не можете привязать неконстантную ссылку к константному объекту, поскольку это нарушит правильность константы, поэтому код не сможет скомпилироваться.

Что вам нужно, это

for (box const& b : uset)
{

}

так что у вас есть ссылка на const box.

У вас нет этой проблемы с вектором, поскольку вектор не заботится о значении элементов. Доступ осуществляется по индексу, а не по значению элемента, поэтому ничто не может сломаться при изменении значения элемента.

Другие вопросы по теме