Почему я получаю 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.
@HolyBlackCat Это ответ, а не комментарий (ИМХО).
То, что сказал @Holy, верно. Это связано с тем, что мутация элементов может испортить их порядок/хэш.





Все ассоциативные контейнеры предоставляют const доступ только к типу ключа, поэтому вы не можете изменить его и нарушить способ доступа контейнера к элементам. Это значит
decltype(*std::unordered_set<box>{}.begin())
дает вам const box&. Вы не можете привязать неконстантную ссылку к константному объекту, поскольку это нарушит правильность константы, поэтому код не сможет скомпилироваться.
Что вам нужно, это
for (box const& b : uset)
{
}
так что у вас есть ссылка на const box.
У вас нет этой проблемы с вектором, поскольку вектор не заботится о значении элементов. Доступ осуществляется по индексу, а не по значению элемента, поэтому ничто не может сломаться при изменении значения элемента.
Вы не можете изменять элементы в наборах (только вставлять и удалять их). Разыменование итераторов набора дает вам
constобъекты.