У меня есть эта проблема преобразования с этим кодом, используя стандарт C ++ 11:
#include<unordered_set>
struct B
{
int x, y;
};
class A
{
struct hash
{
std::size_t operator()( int* const a ) const
{
return std::hash<int>()( *a );
}
};
struct equal_to
{
std::size_t operator()( int* const a, int* const b ) const
{
return std::equal_to<int>()( *a, *b );
}
};
private:
std::unordered_set< int*, hash, equal_to > set;
public:
void push( const B& b )
{
set.insert( &b.x );
}
};
Кто-нибудь знает, почему это? Я могу решить проблему с удалением модификатора «const» в аргументе «push». Но я не хочу этого, потому что аргумент «b» не изменен.
Редактировать .: Мое упрощение кода привело к адресу без ссылки. Я заставил struct B удалить его.
Ключ от set
объявлен как указатель на межд, int*
, Но это:
void push( const B& b )
{
set.insert( &b.x );
}
передает адрес константы int
, int const*
отсюда ошибка компилятора.
Удаление const
из аргумента разрешит ошибку компилятора, как если бы тип ключа int const*
, но оба эти решения будут:
разрешить какую-то другую часть программы, сconst
доступ к B
экземпляр, который был передан push()
, чтобы изменить значение одного из ключей в наборе и нарушить установленный инвариант:
A a;
B b1{17, 22};
B b2{30, 22};
a.push(b1);
a.push(b2);
b1.x = 30; // set no longer contains unique keys.
ввести зависимость от set
на время жизни объекта, на который ссылается b
:
A a;
a.push({14, 23}); // a now contains a dangling pointer.
Самое безопасное решение — хранить int
в качестве ключа см. http://ideone.com/KrykZw для онлайн-демонстрации (спасибо битовая для комментариев).
Возможные решения:
b.x
, Или же,int const*
как ключ. Или предпочтительно (избегая явного динамического выделения),int
в качестве ключа, а не int*
(увидеть http://ideone.com/KrykZw)Других решений пока нет …