【问题标题】:How can I find a const int* in an std::set<int*>?如何在 std::set<int*> 中找到 const int*?
【发布时间】:2013-11-23 02:08:33
【问题描述】:

首先,我有一套

std::set<int*> my_set;

然后,我有一个函数用于检查特定的 int 指针 p 是否存在于 my_set 中,如果指针存在则返回 true,否则返回 false

由于该函数没有修改引用的int,所以很自然地将指针当成const int*,即

bool exists_in_my_set(const int* p)
{
    return my_set.find(p) != my_set.end();
}

但是,当我尝试编译代码时,出现以下错误:

error: invalid conversion from 'const int*' to 'std::set<int*>::key_type {aka int*}' [-fpermissive]

换句话说,当我调用find 时,编译器会尝试将const int* 转换为int*

无论如何,我的问题是:我怎样才能在my_set 中找到p,或者至少找出p 是否存在于my_set 中,使用p 的现有定义和my_set?

【问题讨论】:

  • std::set&lt;int*&gt;::const_iterator 将允许您修改指向的int,因此不应该存在您描述的find 重载。这似乎是我使用 const_cast 的正当理由。
  • 我认为你可以使用 const_cast() 暂时摆脱 'const' 属性。
  • 没有理由超载find。你存储int*,表示可以修改引用的对象!?那你为什么要寻找一个不能修改的对象的引用呢?
  • 也许你的集合应该存储const int*s?
  • @StroyTeller:该函数通过my_set 具有非const 访问权限,但由于它不使用该写访问权限,因此它确实接受它是有意义的一个int const*。否则,本身只有int const* 的函数需要const_cast 才能调用exists_in_my_set。这会产生误导,因为如果exists_in_my_set 正确实现,就没有充分的理由将该调用突出显示为潜在的 const-unsafe。因此,在这种情况下,“良好实践”确实提供了正确的方法:它使非修改函数可以从其他人调用而无需强制转换。

标签: c++ templates pointers find constants


【解决方案1】:

你可以这样声明集合

std::set<const int*> my_set;

...如果你永远不需要通过从集合中获取它的指针来修改int。如果集合中整数的生命周期*和值在其他地方进行管理,并且集合只是一种检查您是否已经知道特定整数/对象存在的方法,则可能会出现这种情况。

(*虽然你实际上可以删除const int*。)

【讨论】:

  • 这在我的情况下确实有效! :) 我想有时候当你发现自己处于这样一个棘手的情况时,你应该问问自己真正的问题是否在你认为的地方。
  • 我猜“删除const int*”是指将其从集合中删除?
【解决方案2】:

在搜索set&lt;&gt;之前,您可以使用const_cast&lt;&gt;从参数中删除常量:

return my_set.find(const_cast<int*>(p)) != my_set.end();

库无法支持您所期望的并没有特别的技术原因,但另一方面 - 强制显式 const_cast 正在记录涉及 const 指针的操作以某种方式变得非const通过set 访问...可以说是不错的文档,但有一些不寻常的东西出现了。

【讨论】:

  • 由于第二段,我现在对此表示赞同。我通常不喜欢没有解释就建议实践的答案。这与@SteveJessop 在 OP 上写的评论一起非常好。
  • 如果 user1158692 的方法不适用,也许这是唯一的好方法。另一方面,如果使用reinterpret_cast&lt;std::set&lt;const int*&gt;&amp;&gt;(my_set)my_set 重新解释为std::set&lt;const int*&gt; 以添加常量而不是删除常量呢?我不知道该方法的行为是否已明确定义,但如果是,我想该方法也可以工作。
  • @HelloGoodbye:从技术上讲,这将是未定义的行为,当const_cast&lt;&gt; 可用时,没有理由进入该领域。实际上,我希望它在任何现实世界的架构/实现中都能正常工作。您的演员表意味着 findend 对于不同的 set 模板参数的额外实例化,可能还有迭代器类型和比较运算符,但它们要么是内联的,要么很小。
  • 好吧,我猜它是未定义的,因为不能保证 std::set&lt;const int*&gt; 使用的所有对象中的成员变量与 std::set,即使他们很可能这样做。因此,将其重新解释为另一种类型可能是个坏主意。
猜你喜欢
  • 2010-11-23
  • 2019-06-25
  • 2023-04-08
  • 2017-09-04
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
相关资源
最近更新 更多