如何明确告诉编译器选择一个模板包扩张期间参数模板?



我正在尝试使用包参数模板来适应某些情况。当列表中只有一个参数时,我想停止模板打包参数的扩展。我希望在实例化模板时显式地使用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...>();
}

最新更新