I would like to get the return type of std::begin
in a generic way. My current solution is:
using type = decltype(std::begin(std::declval<T>()));
and it works when T = std::vector<int>
. But I don't understand why the following does not work:
using type = decltype(std::begin(std::declval<int[3]>()));
I get the error:
example.cpp:83:60: error: no matching function for call to ‘begin(int [3])’
using type = decltype(std::begin(std::declval<int[3]>()));
How to get the return type of std::begin
in a generic way?
C programming does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.
The first and last elements are accessed using an index and the first value is accessed using index 0 and the last element can be accessed through length property which has one more value than the highest array index. The array length property in JavaScript is used to set or return the number of elements in an array.
Return Type − A function may return a value. The return_type is the data type of the value the function returns. Some functions perform the desired operations without returning a value. In this case, the return_type is the keyword void. Function Name − This is the actual name of the function.
The overload for arrays is:
template< class T, std::size_t N >
constexpr T* begin( T (&array)[N] );
And std::declval<int[3]>()
gives you a int(&&)[3]
, which doesn't match that overload. It also doesn't match the normal container overload, because those are SFINAE-ed on having c.begin()
. So you're left with no matching function.
What you need instead is to pass an lvalue reference to array to begin()
, to get the iterator back out. So either you need to manually provide a that lvalue reference when you use your alias:
template <class T>
using type = decltype(std::begin(std::declval<T>()));
using arr = type<int(&)[3]>; // int*
or have the alias itself provide the lvalue reference for you:
template <class T>
using type = decltype(std::begin(std::declval<T&>()));
using arr = type<int[3]>; // int*
The former seems more correct to me, but YMMV.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With