我有一个示例函数,它接受一个数组的引用。函数定义中的元素数量未知。
template<typename T, std::size_t N>
void someFun(T (&)[N])
{
/* ... */
}
为一个元素的数组调用此函数正在编译。
推导的param类型为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]
。你能否解释为什么我不能为零元素数组使用更通用的解决方案?请不要判断此代码的原因。这只是学习目的的一个例子。
答案 0 :(得分:2)
零大小的数组绝对不是标准的C ++。来自[dcl.array]:
然而,在声明
T
D
中D
的格式为
D1 [ constant-expressionopt ] attribute-specifier-seqopt
[...]
如果存在常量表达式,则它应为
std::size_t
类型的转换常量表达式,其值应大于零。
GCC提供零长度的数组作为extension,但由于它们是非标准的,因此您不能指望它们与其他语言功能一起使用,例如模板参数推断。您可以为零长度数组明确重载函数。
#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)上编译。