2

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.

padamowski
  • 139
  • 5
  • 6
    Note [arrays of zero size are an extension and not standard C++](https://stackoverflow.com/q/26209190/1708801) using `-pedantic` to obtain a diagnostic. They are mainly useful for flexible arrays members, they may work by accident in other cases. – Shafik Yaghmour Mar 09 '18 at 22:52
  • 1
    There's no such thing as an array of size 0. The length has to be greater than 0 ([cppreference](http://en.cppreference.com/w/cpp/language/array)) – Justin Mar 09 '18 at 22:53
  • A c-style array cannot have zero size; it's undefined behavior. – max66 Mar 09 '18 at 22:54
  • @max66 It is *not* undefined behaviour, it's simply not allowed by standard C++ and the compiler will give you diagnostic. – Henri Menke Mar 09 '18 at 23:12
  • 1
    I'm surprised nobody has mentioned this but `std::array` is well defined for size zero. And honestly, you should not be using `std::array` anyhow, there's very few reasons to still use a C style array. – Nir Friedman Mar 09 '18 at 23:22
  • @NirFriedman [the content in my link above](https://stackoverflow.com/questions/49203358/how-to-pass-an-array-of-zero-size-to-template-function#comment85412131_49203358) mentioned that. – Shafik Yaghmour Mar 10 '18 at 06:09

1 Answers1

2

Arrays of zero size are definitely not standard C++. From [dcl.array]:

In a declaration T D where D 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).

Henri Menke
  • 10,705
  • 1
  • 24
  • 42
  • @DOUGLASO.MOEN That is of course and option but the question was about arrays, not `std::array`. From the quesion: “It is just an example for learning purposes.” – Henri Menke Mar 10 '18 at 03:47