如何在非常量指针集合中搜索 const 指针?

How to search for const pointer in a collection of non-const pointers?

我有一个成员变量std::set<T*> m_associates;,即非常量原始指针的集合,只是想检查是否存在另一个指针。 为了保持 const 的正确性,我的函数如下所示:

bool MyClass::is_associated(const T* x) const
{
    return (m_associates.find(x) != m_associates.end());
}

但是,这不会编译,因为 x 作为 const T* 传递,表明 x 指向的值未被函数更改,但 m_associates 包含非常量 T*.

如果我从 x 参数中删除 const,它会编译,但违反了常量正确性...

const 添加到 m_associates,即 std::set<const T*> m_associates; 也不是一个选项,因为我在 class.[=25 的其他地方需要非常量指针=]

我该如何解决这个问题?这是应该使用 const_cast 的(可能是唯一的)点吗?或者我是否必须始终将所有参数 T 指针作为非常量传递?

编辑: 完整错误输出,编译器为clang++-8,代码为C++17

error: no matching member function for call to 'find'
        return (m_associates.find(x) != m_associates.end());
                ~~~~~~~~~~~~^~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_set.h:798:7: note: candidate function not viable: 1st argument ('const T *') would lose const qualifier
      find(const key_type& __x) const
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_set.h:804:2: note: candidate function template not viable: 'this' argument has type 'const std::set<T *>', but method is not marked const
        find(const _Kt& __x)
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_set.h:794:7: note: candidate function not viable: 'this' argument has type 'const std::set<T *>', but method is not marked const
      find(const key_type& __x)
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_set.h:810:2: note: candidate template ignored: substitution failure [with _Kt = const T *]: no matching member function for call to '_M_find_tr'
        find(const _Kt& __x) const
        ^

在这种情况下,您可以抛弃 xconst 特性而没有 ill-effects。

除了可能表明设计缺陷外,只有你需要注意的事情是丢弃const是试图修改一个对象的行为最初是通过非 const 指针使用 const 声明的,未定义。这里不是这种情况。

您当前代码失败的原因是 std::set<T> 的默认 Comparestd::less<T>;这强制两个参数都为 T 以进行比较——在本例中为非 const T* 类型。由于 const T* 不能转换为 T* 而不放弃常量,这会导致编译错误。

如果您使用的是 C++14 或更高版本,您可以重新定义您的 std::set,以便 Compare 模板类型是一个透明比较器(推导基础类型进行比较的一个),例如 std::set<T*, std::less<>>。这将启用推导类型并将参数转发给比较器的 std::set::find 的重载,这将使上述代码能够工作。