I have a member variable std::set<T*> m_associates;
, i.e., a collection of non-const raw pointers, and simply want to check for existence of another pointer.
To maintain const correctness my function looks like this:
bool MyClass::is_associated(const T* x) const
{
return (m_associates.find(x) != m_associates.end());
}
However, this does not compile, since x
is passed as const T*
to indicate that the value pointed to by x
is not changed by the function, but m_associates
contains non-const T*
.
If I remove const
from the x
parameter, it compiles, but violates const correctness...
Adding const
to m_associates
, i.e., std::set<const T*> m_associates;
is not an option either as I need the non-const pointers elsewhere in my class.
How do I solve this? Is this (possibly the only) point where a const_cast
should be used? Or do I have to always pass all parameter T
pointers as non-const?
Edit: Full error output, compiler is clang++-8, code is in 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
^
Do not return non-const handles to Class data from const member Functions. From a language point of view, the pointer 'p' is part of the class and then cannot be modified in a 'const' function. But the pointed-to value is not part of the class, and may be modified.
Firstly, int *const does mean a const pointer to a non-const int. So there is absolutely no type mismatching between pointer and pointee types.
A pointer to a const value (sometimes called a pointer to const for short) is a (non-const) pointer that points to a constant value. In the above example, ptr points to a const int . Because the data type being pointed to is const, the value being pointed to can't be changed. We can also make a pointer itself constant.
Const pointers can be NULL. A reference does not have its own address whereas a pointer does. The address of a reference is the actual object's address. A pointer has its own address and it holds as its value the address of the value it points to.
The reason your current code fails is that the default Compare
for std::set<T>
is std::less<T>
; which forces both arguments to be a T
for comparison -- in this case, non-const
T*
types. Since const T*
cannot be converted to T*
without casting away the constness, this is causing your compile errors.
If you are using C++14 or above, you can redefine your std::set
so that the Compare
template type is a transparent comparator (one that deduces the underlying types for comparison), for example std::set<T*, std::less<>>
. This will enable the overload of std::set::find
that deduces the type and forwards the argument to the comparator, which will enable the above code to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With