问题 C ++:在指针集中查找


我的问题通过以下示例说明:

#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指针。


6962
2017-09-16 21:07


起源

正在将集的类型更改为 set<const A*> 一个选项? - Cameron
but is there any solution less ugly and brutal  没有一组指针。 - PaulMcKenzie
const A * 是不一样的 A *! - πάντα ῥεῖ
@PaulMcKenzie一套智能指针不会更好。 - Sneftel
在 find,你正在寻找一个 const 但是,该集合被声明为具有非const元素。 - vsoftco


答案:


一个选项是使用C ++ 14 透明的算子仿函数 和...一起 异构查找

std::set<A*, std::less<>> s;
s.find(cp);

不幸的是,libstdc ++当前不支持异构查找,但是 它被标记为WIP。 (它可以在clang / libc ++和 将有空 在Visual Studio的下一个版本中。)没有它,你几乎被困在了 const_cast“ING cp


10
2017-09-16 21:24



嗯,你快了半分钟。我浏览了github草案并用责备找到那些文档编号.. - dyp
@dyp我作弊并使用了libstdc ++状态页面:) - T.C.
好吧,我至少可以在这里粘贴我的实例(并从OP中删除我的评论)。 coliru.stacked-crooked.com/a/3ab721111ad74620 (“我只证明它编译,没试过”) - dyp
Boost多索引容器已经有很长时间的异构查找。我希望Boost.Container有更多,但当时没有。 - JDługosz


可悲的是, set关键类型(它们确实应该是)的查询方法没有模板化,所以 lower_boundequal_range等等也无济于事。

假设变量类型不可协商,你唯一的选择就是抛弃指针的常量,或者 reinterpret_cast 设置为a set<const A*>。后者在某些方面对我来说更好,但它在技术上是不安全的。

抛弃了常数。使用 const_cast 要做到这一点,要明确这是演员正在做的唯一事情。如果你愿意,将它包装在一个自由函数中;如果一段代码是邪恶的,那么制造邪恶的东西是个好主意 只要 它做的事情。


2
2017-09-16 21:14



“可悲的是,set的查询方法并没有模仿关键类型(它们确实应该是)” 这有其缺点。我记得由异构查找成员函数和同类比较函数(导致每次比较转换)引起的错误。见T.C.的答案。 - dyp


您可以将find与const_cast一起使用:

s.find(const_cast<A*>(cp));

2
2017-09-16 21:17