如何在非常量指针集合中搜索 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
^
在这种情况下,您可以抛弃 x
的 const
特性而没有 ill-effects。
除了可能表明设计缺陷外,只有你需要注意的事情是丢弃const
是试图修改一个对象的行为最初是通过非 const
指针使用 const
声明的,未定义。这里不是这种情况。
您当前代码失败的原因是 std::set<T>
的默认 Compare
是 std::less<T>
;这强制两个参数都为 T
以进行比较——在本例中为非 const
T*
类型。由于 const T*
不能转换为 T*
而不放弃常量,这会导致编译错误。
如果您使用的是 C++14 或更高版本,您可以重新定义您的 std::set
,以便 Compare
模板类型是一个透明比较器(推导基础类型进行比较的一个),例如 std::set<T*, std::less<>>
。这将启用推导类型并将参数转发给比较器的 std::set::find
的重载,这将使上述代码能够工作。
我有一个成员变量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
^
在这种情况下,您可以抛弃 x
的 const
特性而没有 ill-effects。
除了可能表明设计缺陷外,只有你需要注意的事情是丢弃const
是试图修改一个对象的行为最初是通过非 const
指针使用 const
声明的,未定义。这里不是这种情况。
您当前代码失败的原因是 std::set<T>
的默认 Compare
是 std::less<T>
;这强制两个参数都为 T
以进行比较——在本例中为非 const
T*
类型。由于 const T*
不能转换为 T*
而不放弃常量,这会导致编译错误。
如果您使用的是 C++14 或更高版本,您可以重新定义您的 std::set
,以便 Compare
模板类型是一个透明比较器(推导基础类型进行比较的一个),例如 std::set<T*, std::less<>>
。这将启用推导类型并将参数转发给比较器的 std::set::find
的重载,这将使上述代码能够工作。