Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
        ^
like image 846
Gileos Avatar asked Aug 11 '20 13:08

Gileos


People also ask

Can a const function return a non-const pointer?

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.

How would you write a const pointer to a non-const int in C++?

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.

Is a non-const pointer that points to a constant value?

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.

Is const pointer same as reference?

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.


1 Answers

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.

like image 132
Human-Compiler Avatar answered Sep 22 '22 05:09

Human-Compiler