С++: найти в наборе указателей
Моя проблема проиллюстрирована следующим примером:
#include <set>
class A {};
int main()
{
A a;
A * p = &a;
const A * cp = &a;
std::set<A*> s;
s.insert(p);
s.find(cp);
}
Компиляция заканчивается на:
a.cpp: In function ‘int main()’:
a.cpp:13:18: error: invalid conversion from ‘const A*’ to ‘std::set<A*>::key_type {aka A*}’ [-fpermissive]
s.find(cp);
^
In file included from /usr/include/c++/4.9.1/set:61:0,
from a.cpp:1:
/usr/include/c++/4.9.1/bits/stl_set.h:701:7: note: initializing argument 1 of ‘std::set<_Key, _Compare, _Alloc>::iterator std::set<_Key, _Compare, _Alloc>::find(const key_type&) [with _Key = A*; _Compare = std::less<A*>; _Alloc = std::allocator<A*>; std::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<A*>; std::set<_Key, _Compare, _Alloc>::key_type = A*]’
find(const key_type& __x)
Я знаю, почему он не компилируется, но есть ли решение, менее уродливое и жестокое, чем s.find((A*)cp)
? Указаны указатель set и const.
Ответы
Ответ 1
Опция заключается в использовании С++ 14 прозрачных операторов-операторов вместе с гетерогенный поиск:
std::set<A*, std::less<>> s;
s.find(cp);
К сожалению, гетерогенный поиск в настоящее время не поддерживается в libstdС++, но он помечен как WIP. (Доступно в clang/libС++ и будет доступно в следующей версии Visual Studio.) Без этого вы в значительной степени застреваете с const_cast
'ing cp
.
Ответ 2
Трагически, методы запроса set
не имеют шаблонов для типа ключа (они действительно должны быть), поэтому lower_bound
, equal_range
и т.д. не помогут.
Ваши единственные варианты, предполагая, что типы переменных не подлежат обсуждению, должны отбросить указатель-константу или reinterpret_cast
, установленный в set<const A*>
. Последний в некотором смысле чувствует себя приятнее для меня, но это технически небезопасно.
Отбросьте константу. Используйте const_cast
, чтобы сделать это, чтобы было ясно, что это единственное, что делает актерский состав. Если вам нравится, оберните это и найдите в свободной функции; если часть кода зла, это хорошая идея, чтобы сделать злую вещь единственной, что она делает.
Ответ 3
Вы можете использовать find с помощью const_cast:
s.find(const_cast<A*>(cp));