【问题标题】:How to search for const pointer in a collection of non-const pointers?如何在非常量指针集合中搜索 const 指针?
【发布时间】:2023-03-12 01:38:01
【问题描述】:

我有一个成员变量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 包含非const T*

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

const 添加到m_associates,即std::set<const T*> m_associates; 也不是一个选项,因为我需要在我的班级的其他地方使用非常量指针。

我该如何解决这个问题?这是(可能是唯一的)应该使用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
        ^

【问题讨论】:

  • 这里添加 const 应该没有问题。你绝对不应该违反 const-correcteness。
  • 您从发布的代码中得到什么错误?
  • 您使用的是哪个版本的 C++?如果您在 std::set 上使用透明比较器,C++14 及更高版本将允许此操作
  • 使用C++17和clang++-8,我将错误输出添加到正文中

标签: c++ const-correctness


【解决方案1】:

在这种情况下,您可以抛弃xconst-ness 而不会产生不良影响。

除了可能表示设计缺陷之外,唯一在抛弃 const 时需要注意的是,尝试修改最初使用 const 声明的对象时的行为通过非const 指针未定义。这里不是这样。

【讨论】:

    【解决方案2】:

    您当前代码失败的原因是std::set&lt;T&gt; 的默认Comparestd::less&lt;T&gt;;这会强制两个参数都是 T 以进行比较——在这种情况下,非const T* 类型。由于const T* 不能在不丢弃常量的情况下转换为T*,这会导致您的编译错误。

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

    【讨论】:

    • 很好。投赞成票。 (我个人认为 C++ 标签现在已经移到了 C++14。即使是我和我的陈旧的杜迪程序现在也移到了 C++14。)
    • @Bathsheba That's nice. Have an upvote. 总是很高兴在 S.O. 上看到一位绅士。紫外线两个答案
    • @Gileos 不幸的是,这是在没有const_cast 的情况下使用std::set::find 解决此问题的唯一方法。如果这对更改的侵入性太大,则使用此功能的唯一方法是将const_cast const T* 更改为T* 以便比较可以工作,或者只是不使用std::set::find(例如子最好通过std::find 搜索)
    • @Gileos 类型别名很好。使代码支持更容易,并避免人们试图穿过人字形( 对)的森林。
    • 这是我最喜欢的“C++ 有点笨”的论调之一!
    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    • 2021-08-25
    相关资源
    最近更新 更多