如何将零大小的数组传递给模板函数

How to pass an array of zero size to template function

我有一个引用数组的示例函数。函数定义中的元素数量未知。

template<typename T, std::size_t N>
void someFun(T (&)[N])
{
    /* ... */
}

为一个元素的数组调用此函数编译正常。 推导的参数类型是 int (&)[1].

int main()
{
    int arr[1];
    someFun(arr);
}

问题是,当我试图传递零元素数组时。下面的示例显示了代码和错误。

int main()
{
    int arr[0];
    someFun(arr);
}

编译错误(使用 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

我假设推导的模板参数类型是 int (&)[0],但是这个参数的替换失败了。我可以通过重载 someFun 来绕过。这是我的工作示例:

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);
}

运行 此代码导致调用 void someFun(T (&)[0]) 函数,推导的参数类型为 int (&)[0]。您能否解释一下为什么我不能对零元素数组使用更通用的解决方案?请不要判断这段代码的原因。这只是一个学习目的的例子。

零大小的数组绝对不是标准的 C++。来自 [dcl.array]:

In a declaration T D where D has the form

D1 [ <em>constant-expression</em><sub>opt</sub> ] <em>attribute-specifier-seq</em><sub>opt</sub>

[...]

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 然而提供零长度的数组作为 extension 但因为它们是 non-standard 你不能指望它们与其他语言特性一起工作,例如模板参数推导。您可以为零长度数组显式重载函数。

#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);
}

这可以在 GCC (7.2.0) 上编译,但不能在 Clang (6.0.0) 上编译。