Consider the following code:
struct A
{
using type = int;
using reference = int&;
};
static_assert(std::is_same_v<A::type&, A::reference>); // <-- Success, as it would be
static_assert(std::is_same_v<const A::type&, const A::reference>); // <-- Fail!!
What is going on?? Why they are not the same type anymore? I spent lot of time finding this and it really seems a compiler bug
First, const int&
is, so to speak, a reference to constant int, not a constant reference to int. Thus adding const
keyword to A::reference
produces a beast that spelled as int& const
instead of const int&
(or equally fine int const &
).
So yes, as a reference cannot be rebound to different object, it is de facto constant without any keywords. Thus that const
after an ampersand is excessive. Looks like it is silently dropped, I cannot cite standard on required compiler behavior, see comment by @Quentin.
Second, the answer may depend on what you really want to achieve. If A
is a container, it should have a A::const_reference
member type, which you should use. If it is a more generic range rather than a container, its reference
and const_reference
member types might be two completely unrelated proxy object classes. If you control A
, add a const_reference
member type. Otherwise, @Evg provided a solution that will do. Maybe a more simple solution is just const std::decay_t<A::reference>&
.