I have an example function which takes a reference to an array. The number of elements in the function definition is unknown.
template<typename T, std::size_t N>
void someFun(T (&)[N])
{
/* ... */
}
Calling this function for an array of one element is compiling fine.
Deduced param type is int (&)[1]
.
int main()
{
int arr[1];
someFun(arr);
}
The problem is, when I'm trying to pass an array of zero elements. Example below shows the code and error.
int main()
{
int arr[0];
someFun(arr);
}
Compilation error (using g++ 7.2):
../src/main.cpp: In function 'int main()':
../src/main.cpp:24:13: error: no matching function for call to 'someFun(int [0])'
someFun(arr);
^
../src/main.cpp:9:6: note: candidate: template<class T, long unsigned int N> void someFun(T (&)[N])
void someFun(T (&a)[N])
^~~~~~~
../src/main.cpp:9:6: note: template argument deduction/substitution failed:
make: *** [src/main.o] Error 1
I assume that deduced template param type is int (&)[0]
, however the substitution of this argument failed. I can go around by overloading someFun
. Here is my working example:
template<typename T, std::size_t N>
void someFun(T (&)[N])
{
/* ... */
}
template<typename T>
void someFun(T (&)[0])
{
/* ... */
}
int main()
{
int arr[0];
someFun(arr);
}
Running this code leads to a call to void someFun(T (&)[0])
function and deduced param type is int (&)[0]
. Could you please explain why I can't use more generic solution for an array of zero elements? Please don't judge the reason of this code. It is just an example for learning purposes.
Arrays of zero size are definitely not standard C++. From [dcl.array]:
In a declaration
T
D
whereD
has the form
D1 [ constant-expressionopt ] attribute-specifier-seqopt
[...]
If the constant-expression is present, it shall be a converted constant expression of type
std::size_t
and its value shall be greater than zero.
GCC however provides arrays of zero length as an extension but since they are non-standard you can't expect them to work together with other language features, such as template argument deduction. You could make an explicit overload of the function for zero length arrays.
#include <cstdlib>
template<typename T, std::size_t N>
void someFun(T (&)[N]) {}
template<typename T>
void someFun(T (&)[0]) {}
int main() {
int arr[0];
someFun(arr);
}
This compiles on GCC (7.2.0) but not on Clang (6.0.0).