Potentially related articles:
For a STL container C
, std::begin(C)
and similar access functions including std::data(C)
(since C++17) are supposed to have the same behavior of C::begin()
and the other corresponding C
's methods. However, I am observing some interesting behaviors due to the details of overload resolution involving lvalue/rvalue references and constness.
DataType1
is int*
as easily expected. Also, confirmed the by with Boost's type_id_with_cvr
. const vector<int>
gives int const*
No surprise here.
using T = vector<int>;
using DataType1 = decltype(T().data()); // int*
using CT = const T;
using DataType2 = decltype(CT().data()); // int const*
using boost::typeindex::type_id_with_cvr;
cout << type_id_with_cvr<DataType1>() << endl; // prints int*
...
I tried std::data
, which can also handle arrays and non-STL containers. But it yields int const*
. Similarly, std::begin
returns a const iterator, even though T
is not const.
using T = vector<int>;
using DataType3 = decltype(std::data(T())); // int const* Why ???
using CT = const T;
using DataType4 = decltype(std::data(CT())); // int const*
Question: What is the reason of this difference? I expected that C.data()
and std::data(C)
would behave in the same manner.
Some my research: In order to get int*
for DataType3
, T
must be converted to non-const lvalue reference type explicitly. I tried declval
, and it was working.
using DataType3 = decltype(std::data(std::declval<T&>())); // int*
std::data
provides two overloads:
template <class _Cont> constexpr
auto data(_Cont& __c) -> decltype(__c.data()) { return __c.data(); }
// non-const rvalue reference argument matches to this version.
template <class _Cont> constexpr
auto data(const _Cont& __c) -> decltype(__c.data()) { return __c.data(); }
While resolving overloaded functions for std::data
, T()
, which is non-const rvalue reference, is matched to the const T&
version instead of T&
version.
It was not easy to find this specific overload resolution rule in the standard (13.3, over.match). It'd be much clearer if someone could point the exact rules for this issue.