调用 std::set<Type*>::find 时避免 const_cast
Posted
技术标签:
【中文标题】调用 std::set<Type*>::find 时避免 const_cast【英文标题】:Avoiding const_cast when calling std::set<Type*>::find 【发布时间】:2016-05-09 14:11:59 【问题描述】:有什么好的方法可以避免下面的const_cast
,同时保持 const 的正确性?
如果没有const_cast
,下面的代码将无法编译。 set::find
获得对集合键类型的 const 引用,因此在我们的例子中,它保证不会更改传入的指针值;但是,它不能保证不改变指针指向的内容。
class C
public:
std::set<int*> m_set;
bool isPtrInSet(const int* ptr) const
return m_set.find(const_cast<int*>(ptr)) != m_set.end();
;
【问题讨论】:
您在一个返回bool
的函数中返回一个迭代器,此代码当前无法编译。你的意思是使用return m_set.find(const_cast<int*>(ptr)) != std::cend(m_set);
?
糟糕,已修复。谢谢
std::find
可以提供帮助。我想知道他们是否曾经部分专门化它以在 std::set
边界上以对数时间运行。
【参考方案1】:
是的。
在 C++14 中,您可以使用自己的比较器,将int const*
声明为透明。这将启用find()
的template overload,可以将键与任意类型进行比较。请参阅此相关SO question。这是Jonathan Wakely's explanation。
【讨论】:
【参考方案2】:我想解释一下为什么这是不可能的基本逻辑。
假设set<int*>::find(const int*)
是合法的。然后您可以执行以下操作:
set<int*> s;
const int* p_const;
// fill s and p
auto it = s.find(p_const);
int* p = *it;
嘿,快!您将const int*
转换为int*
而不执行const_cast
。
【讨论】:
按照你的逻辑比较 const 和非 const 指针应该是非法的,或者有人可以通过find_if()
制造这个骗局。非常复杂的逻辑恕我直言【参考方案3】:
有没有什么好的方法可以避免下面的 const_cast,同时保持 const 的正确性?
我不确定我要提出的建议是否属于“好方法”。但是,如果您不介意自己迭代集合的内容,则可以避免使用 const_cast
。请记住,这会将 O(log(N)) 操作转换为 O(N) 操作。
bool isPtrInSet(const int* ptr) const
for ( auto p : m_set )
if ( p == ptr )
return true;
return false;
【讨论】:
是否有人会为了避免 const_cast 而付出 O(N) vs O(log(N))? @Slava,我不会,但我不能代表所有人。以上是关于调用 std::set<Type*>::find 时避免 const_cast的主要内容,如果未能解决你的问题,请参考以下文章
插入 std::set<std::tuple<std::string, ...>> 时重复
对于操作计数()。 std::set<void*> 或 std::unordered_set<void*> 哪个更快?
std::multimap<key, value> 和 std::map<key, std::set<value> 有啥区别?
函数对象无法识别它获得的 param(std::set<int>)
linux C++获取两个std::set容器差异(容器元素差异)(容器元素差别)std::set_differencestd::inserter