C++ template parameter deduction for std::array with non size_t integer

arrays, c++, c++11, integer, template-argument-deduction

Solution

`std::array` is templated as:

template<class T, std::size_t N > struct array;

while the size `N` is required to be the type `size_t`. But in your function, you are passing an unsigned (int) which cannot be interpreted as `size_t`. According to SFINAE If a template cannot be deduced, it does not exist, thus your templated function does not exist.

It is NOT the problem with the call line, but your declaration of your function template. To correct this, use the correct type:

template <typename T, size_t Size>
int nextline(const typename std::array<T, Size> ar) {
  return 0;
 }

In this case, even you use:

nextline(std::array<int, 2ul> { 1,0 });

It still works because it can be deduced and casted.

Additional explanation by dyp:

[temp.deduct.type]/17 for non-type template parameters that requires the type of the deduced thing (template-argument) to be of the same type as the template-parameter it is deduced for.

Problem

I'm trying to adapt the solution presented in Avoiding struct in variadic template function to my need. However, I can't understand the the behavior of G++. Consider the following function: ``` template <typename T, unsigned Size> int nextline(const typename std::array<T, Size> ar) { return 0; } ``` Then the call ``` nextline(std::array<int, 2> { 1,0 }); ``` doesn't match with GCC complaining with ``` eslong.cpp: In function ‘int main()’: eslong.cpp:10:38: error: no matching function for call to ‘nextline(std::array<int, 2ul>)’ nextline(std::array<int, 2> { 1,0 }); ^ eslong.cpp:10:38: note: candidate is: eslong.cpp:4:5: note: template<class T, unsigned int Size> int nextline(std::array<T, Size>) int nextline(const typename std::array<T, Size> ar) { ^ eslong.cpp:4:5: note: template argument deduction/substitution failed: eslong.cpp:10:38: note: mismatched types ‘unsigned int’ and ‘#‘integer_cst’ not supported by dump_type#<type error>’ nextline(std::array<int, 2> { 1,0 }); ^ eslong.cpp:10:38: note: ‘std::array<int, 2ul>’ is not derived from ‘std::array<T, Size>’ ``` However it matches if I changes `unsigned Size` to `unsigned long Size` or `size_t`. I'm not sure to understand what's happening here. Isn't the `Size` parameter in the call to `std::array<T, Size>` converted to a `size_t` ?

Original source