You said yourself, decltype (*this)
is T&
. decltype (*this) const &
tries to form a reference to a reference (T& const &
). decltype
triggers the reference collapsing rule 8.3.2p6. But it doesn't collapse the way you'd like.
You could say decltype(this) const&
, but that would be T* const&
-- a reference to a const pointer, not a pointer to a const object. For the same reason, decltype (*this) const
and const decltype (*this)
don't form const T&
, but (T&) const
. And top-level const
on a reference is useless, since references already forbid rebinding.
Perhaps you are looking for something more like
const typename remove_reference<decltype(*this)>::type &
But note that you don't need the cast at all when adding const
. Instead of
DynamicArray const& _this = static_cast<decltype(*this) const&>(*this);
just say
DynamicArray const& _this = *this;
These combine to
const typename std::remove_reference<decltype(*this)>::type & this_ = *this;
Still, this is a stupid amount of code for a very simple and pervasive problem. Just say:
const auto& this_ = *this;
FYI here's the text of the reference collapsing rule:
If a typedef-name (7.1.3, 14.1) or a decltype-specifier (7.1.6.2) denotes a type
TR
that is a reference to a typeT
, an attempt to create the type "lvalue reference to cvTR
" creates the type "lvalue reference toT
", while an attempt to create the type "rvalue reference to cvTR
" creates the typeTR
.
decltype(*this)
is our decltype-specifier which denotes TR
, which is DynamicArray<DatumT>&
. Here, T
is DynamicArray<DatumT>
. The attempt TR const&
is the first case, attempt to create lvalue reference to (const) TR
, and therefore the final result is T&
, not const T&
. The cv-qualification is outside the innermost reference.