我正在尝试使用包参数模板来适应某些情况。当列表中只有一个参数时,我想停止模板打包参数的扩展。我希望在实例化模板时显式地使用typename,而不是使用typename来声明变量。
下面是一个简单的例子:
template <class T>
void f() {}
template <class T, class... Args>
void f() {
f<Args...>();
}
int main() {
f<int, int, double>();
return 0;
}
当编译代码时,我得到了错误:
demo.cc: In instantiation of ‘void f() [with T = int; Args = {double}]’:
demo.cc:6:13: required from ‘void f() [with T = int; Args = {int, double}]’
demo.cc:10:23: required from here
demo.cc:6:13: error: call of overloaded ‘f<double>()’ is ambiguous
6 | f<Args...>();
| ~~~~~~~~~~^~
demo.cc:2:6: note: candidate: ‘void f() [with T = double]’
2 | void f() {}
| ^
demo.cc:5:6: note: candidate: ‘void f() [with T = double; Args = {}]’
5 | void f() {
| ^
我从cppreference网站上读到了以下信息:
带省略号的模式,其中至少有一个参数包的名称出现至少一次,该模式扩展为0个或多个以逗号分隔的模式实例,其中参数包的名称按顺序由包中的每个元素替换。
这可能是为什么编译器不能决定是使用void f() [with T = double]
还是void f() [with T = double; Args = {}]
我可以只使用模板形参而不是使用函数的输入参数来停止解包吗?
您可以使用SFINAE约束该函数的可变版本,以阻止在参数包为空时调用它。它看起来像
template <class T, class... Args, std::enable_if_t<(sizeof...(Args) > 0), bool> = true>
void f() {
f<Args...>();
}