有简单的方法吗?不可以。可以使用一堆乱码的模板来完成吗?当然,为什么不呢。
执行
首先,如果我们有一个类而不是一个函数,这将更容易一些,因为参数化的类可以作为模板参数传递。所以我要在你的myFunc.
template <bool... Acc>
struct MyFuncWrapper {
template <typename T>
void operator()(T&& extra) const {
return myFunc<Acc...>(std::forward<T&&>(extra));
}
};
这只是一个MyFuncWrapper<...>()(extra)相当于的类myFunc<...>(extra)。
现在让我们制作我们的调度程序。
template <template <bool...> class Func, typename Args, bool... Acc>
struct Dispatcher {
auto dispatch(Args&& args) const {
return Func<Acc...>()(std::forward<Args&&>(args));
}
template <typename... Bools>
auto dispatch(Args&& args, bool head, Bools... tail) const {
return head ?
Dispatcher<Func, Args, Acc..., true >().dispatch(std::forward<Args&&>(args), tail...) :
Dispatcher<Func, Args, Acc..., false>().dispatch(std::forward<Args&&>(args), tail...);
}
};
唷,那里有很多要解释的。该类Dispatcher有两个模板参数,然后是一个可变参数列表。前两个参数很简单:我们想要调用的函数(作为一个类)和“额外”参数类型。可变参数将开始为空,我们将在递归期间将其用作累加器(类似于进行尾调用优化时的累加器)来累积模板布尔列表。
dispatch只是一个递归模板函数。基本情况是当我们没有任何参数时,所以我们只是用我们迄今为止积累的参数调用函数。递归情况涉及一个条件,我们累积 a trueif the Boolean istrue和 a falseif it's false。
我们可以用
Dispatcher<MyFuncWrapper, TypeOfExtraArgument>()
.dispatch(extraArgument, true, true, false);
但是,这有点冗长,因此我们可以编写一个宏以使其更易于使用。1
#define DISPATCH(F, A, ...) Dispatcher<F, decltype(A)>().dispatch(A, __VA_ARGS__);
现在我们的电话是
DISPATCH(MyFuncWrapper, extraArgument, true, true, false);
完整的可运行示例
包括一个示例myFunc实现。
#include <utility>
#include <iostream>
#define DISPATCH(F, A, ...) Dispatcher<F, decltype(A)>().dispatch(A, __VA_ARGS__);
template <bool a, bool b, bool c, typename T>
void myFunc(T&& extra) {
std::cout << a << " " << b << " " << c << " " << extra << std::endl;
}
template <bool... Acc>
struct MyFuncWrapper {
template <typename T>
void operator()(T&& extra) const {
return myFunc<Acc...>(std::forward<T&&>(extra));
}
};
template <template <bool...> class Func, typename Args, bool... Acc>
struct Dispatcher {
auto dispatch(Args&& args) const {
return Func<Acc...>()(std::forward<Args&&>(args));
}
template <typename... Bools>
auto dispatch(Args&& args, bool head, Bools... tail) const {
return head ?
Dispatcher<Func, Args, Acc..., true >().dispatch(std::forward<Args&&>(args), tail...) :
Dispatcher<Func, Args, Acc..., false>().dispatch(std::forward<Args&&>(args), tail...);
}
};
int main() {
DISPATCH(MyFuncWrapper, 17, true, true, false);
DISPATCH(MyFuncWrapper, 22, true, false, true);
DISPATCH(MyFuncWrapper, -9, false, false, false);
}
结语
上面提供的实现也将允许myFunc返回值,尽管您的示例仅包含返回类型void,所以我不确定您是否需要它。如所写,实现需要 C++14 作为auto返回类型。如果您想在 C++11 下执行此操作,您可以将所有返回类型更改为void(不能再返回任何内容myFunc),或者您可以尝试将返回类型与decltype. 如果你想在 C++98 中做到这一点,………………祝你好运
1此宏容易受到逗号问题的影响,因此如果您将零布尔值传递给它,它将无法工作。但是如果你不打算传递任何布尔值,你可能无论如何都不应该经历这个过程。