假设我在编译时需要执行一些操作:
enum class Action {A, B};
现在,我编写一个模板可变参数函数,该函数可以按顺序执行动作的可能组合:
template <Action a>
void applyAction();
template <typename = void>
void applyActions() {}
template <Action a, Action... as>
void applyActions() {
applyAction<a>();
applyActions<as...>();
}
此代码很好。确实:
void foo() {
applyActions<Action::A, Action::B>();
}
正确生成:
call void applyAction<(Action)0>()
call void applyAction<(Action)1>()
为了实现扩展包终止,我必须声明虚拟函数:
template <typename = void> void applyActions() {}
这对我来说很“丑陋”,因为它可以调用通用类型。
在C ++ 11中,有没有办法声明一个接受空参数包的可变参数函数?
当然,它的声明不必使用所需的函数来引起歧义:
template <Action a, Action... as>
void applyActions();
类似的东西:
template <Action.. = {}>
void applyActions() {}
Here这是一个不可编译的示例,因为通话不明确。但是它给出了我想要实现的目标。
答案 0 :(得分:5)
以下一种结构化方式可以删除“丑陋”的默认值,它也删除了递归并可以与空的动作参数包一起使用
#include <iostream>
using namespace std;
enum class Action {A, B};
template <Action a>
void applyAction()
{
std::cout << "Action " << (int)a << std::endl;
}
template <Action... as>
void applyActions() {
using do_= int[];
(void)do_{0, (
applyAction<as>()
,0)...};
}
void foo() {
applyActions<Action::A, Action::B>();
}
void bar() {
applyActions<Action::B, Action::A>();
}
int main() {
foo();
bar();
return 0;
}
正如HolyBlackCat指出的那样,在c ++ 17中,您可以只使用fold表达式,
template <Action... as>
void applyActions() {
(applyAction<as>(), ...);
}
答案 1 :(得分:1)
在C ++ 11中,是否有一种方法可以声明一个接受空参数包的可变参数函数?
是的:这很简单
template <Action...>
void applyActions()
问题是,在您的情况下,该函数与接受一个或多个元素的函数发生冲突
template <Action a, Action... as>
void applyActions()
,当您使用非空的applyActions<as...>();
包呼叫as...
时,两个模板都匹配。
使用名称相同但类型不同的模板函数(以及默认值)
template <typename = void>
void applyActions() {}
这(IMHO)是一种非常聪明,便宜且优雅的解决终端问题的方法。