I want to create the following class, but the compiler gives an error (it tells that the signatures of the methods are the same):
struct entities_set_less
{
constexpr bool operator()(const ContentEntity*& _Left, const ContentEntity*& _Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
constexpr bool operator()( const const ContentEntity*& _Left, const const ContentEntity*&_Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
};
From my point of view, an expression like const const ContentEntity*&
means "const reference to pointer on const ContentEntity". It should be different from const ContentEntity*&
, which is just "const reference to pointer on non const type".
CodePudding user response:
I believe a lot of confusion about what the const
applies to can be removed by adopting the east-const
convention:
const reference to pointer on const ContentEntity
ContentEntity const* const&
const reference to pointer on non const type
ContentEntity* const&
This way, you know that the const
always refers to what's on its left.
Also, when in doubt, I usually check on cdecl the type of the variables I'm declaring.
CodePudding user response:
const const
is never correct. The rule to remember is that const
applies to whatever is on its left. The exception is when const
is the leftmost token, in which case it applies to the right. So, when you want to add const
, add it to the right side of whatever you want to be const
.
How to create const reference to pointer on const?
So, let's start with a reference to a pointer:
ContentEntity*&
We want it to be a reference to a const pointer. We place const
to the right of *
. Since it applies to left, this means that the referred pointer is const:
ContentEntity* const &
We want it to be a const pointer to const object of type ContentEntity
. We place const
to the right of ContentEntity
. Since it applies to left, this means that the pointed ContentEntity
is const:
ContentEntity const * const &
Alternatively, since ContentEntity
is the first token, we can place its const to the left:
const ContentEntity * const &
All that said, it's quite rare to explicitly use a reference to const a pointer. It's more typical to pass a copy of the reference. References to const pointers do occur often when instantiating templates.
CodePudding user response:
First, let's clarify (or attempt to) what you actually want. You say you want a "const reference" … but references are (effectively) const
, anyway (i.e., once a reference variable is bound to its target, it cannot subsequently be bound to a different target).
So, what you may have meant is that you want the arguments in the second overload to be references to constant pointers to constant objects; that is, neither the pointers nor the objects can be modified (in your first overload, the pointed-to objects cannot be modified but the referred-to pointers can be.
To make the pointers const
, you need to add that keyword immediately after the pointer indicator (*
). Like this:
struct entities_set_less {
constexpr bool operator()(const ContentEntity*& _left, const ContentEntity*& _light) const
{ // references to non-const pointers to const objects
return (_left < _light);
}
constexpr bool operator()(const ContentEntity* const& _left, const ContentEntity* const& _right) const
{ // references to CONST pointers to const objects
return (_left < _right);
}
};
Note that I have also changed your _Left
and _Right
identifiers to _left
and _right
, because IDs starting with an underscore followed by an uppercase letter are reserved. From this C 17 Draft Standard:
5.10 Identifiers [lex.name]
…
(3.1) — Each identifier that contains a double underscore__
or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.