【问题标题】:Avoiding const_cast when calling std::set<Type*>::find调用 std::set<Type*>::find 时避免 const_cast
【发布时间】:2016-09-04 05:16:48
【问题描述】:

有什么好的方法可以避免下面的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&lt;int*&gt;(ptr)) != std::cend(m_set);
  • 糟糕,已修复。谢谢
  • std::find 可以提供帮助。我想知道他们是否曾经部分专门化它以在 std::set 边界上以对数时间运行。

标签: c++ set constants const-cast


【解决方案1】:

是的

在 C++14 中,您可以使用自己的比较器,将int const* 声明为透明。这将启用find()template overload,可以将键与任意类型进行比较。请参阅此相关SO question。这是Jonathan Wakely's explanation

【讨论】:

    【解决方案2】:

    我想解释一下为什么这是不可能的基本逻辑。

    假设set&lt;int*&gt;::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,我不会,但我不能代表所有人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    相关资源
    最近更新 更多