Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the return type of begin on a c array

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?

like image 346
Vincent Avatar asked Feb 02 '17 18:02

Vincent


People also ask

What is the return type of array in C?

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.

How do you access the first element of an array?

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.

What is return type in C?

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.


1 Answers

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.

like image 166
Barry Avatar answered Oct 15 '22 06:10

Barry