Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't pass 'const pointer const' to const ref

Suppose you have a set of pointers (yeah...) :

std::set<SomeType*> myTypeContainer;

Then suppose that you want to search this set from a const method of SomeType:

bool SomeType::IsContainered() const
{
    return myTypeContainer.find(this) != myTypeContainer.end();
}

This doesn't work. The this ptr in the method is a const SomeType *const, which I can't put into the find. The issue being that find takes a const-ref, which in this case would mean that the passed pointer is treated as const, but not the thing it points to.

Is there a way to resolve this smoothly (without changing the set template type)?

like image 399
Thomas B. Avatar asked Mar 01 '18 09:03

Thomas B.


People also ask

Why can't you assign a const reference to a non const reference?

because it immediately violates the rules of const-correctness. so what you are saying is that there is no implicit conversion taking place on x "from int to const int " during reference binding is that right? If yes can you provide link to the standard of the statement which proves your point..

Can you reassign a const pointer?

Constants are block-scoped, much like variables declared using the let keyword. The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be redeclared (i.e. through a variable declaration).

Can you dereference a const pointer?

A const pointer to a const value can not have its address changed, nor can the value it is pointing to be changed through the pointer. It can only be dereferenced to get the value it is pointing at.

Can references be const?

The grammar doesn't allow you to declare a “const reference” because a reference is inherently const . Once you bind a reference to refer to an object, you cannot bind it to refer to a different object.


2 Answers

In order to enable "mixed" comparison in an ordered container, you can use a key_compare type that declares the typename key_compare::is_transparent.

The default comparison functor class of set is std::less<Key>. It is not "transparent". But std::less<void> is "transparent" and performs the comparison of any arguments a and b as long as a<b is well formed. So you could define your own comparison functor type or you could use std::less<void> (or equivalently std::less<>):

set<SomeType*,std::less<>> myTypeContainer;

like image 130
Oliv Avatar answered Nov 15 '22 02:11

Oliv


As you said, in the const member function this becomes const SomeType * (i.e. pointer to const), it can't be implicitly converted to SomeType * (i.e. pointer to non-const), which is the expected parameter type of find.

You could use const_cast to perform explicit conversion.

bool SomeType::IsContainered() const
{
    return myTypeContainer.find(const_cast<SomeType *>(this)) != myTypeContainer.end();
}

It would be safe if the cast result is not used for modifying; while std::set::find won't do that.

like image 10
songyuanyao Avatar answered Nov 15 '22 04:11

songyuanyao