有简单的方法吗?不可以。可以使用一堆乱码的模板来完成吗?当然,为什么不呢。
实施
首先,如果我们有一个类而不是一个函数,这会更容易一些,因为参数化的类可以作为模板参数传递。所以我要在你的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 类有两个模板参数和一个可变参数列表。前两个参数很简单:我们想要调用的函数(作为一个类)和“额外”参数类型。可变参数开始时为空,我们将在递归过程中将其用作累加器(类似于tail call optimization 时的累加器)来累加模板布尔列表。
dispatch 只是一个递归模板函数。基本情况是当我们没有任何参数时,所以我们只是用我们迄今为止积累的参数调用函数。递归情况涉及一个条件,如果布尔值是true,我们累积一个true,如果它是false,我们累积一个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 此宏易受comma problem 的影响,因此如果您将零布尔值传递给它,它将无法工作。但如果你不打算传递任何布尔值,你可能无论如何都不应该经历这个过程。