这可以有效地完成。但是,当我说您问错问题时,请相信我。因此,接下来的内容回答了您的问题,即使几乎总是认为这样做是一个坏主意。
实际上,您可以做的是创建 50 个不同的程序,为 50 种可能的大小中的每一种创建一个,然后有条件地跳转到您想要的那个。
template<int n>
struct prog {
void run() {
// ...
}
};
template<int n>
struct switcher {
void run(int v) {
if(v==n)
prog<n>::run();
else
switcher<n-1>::run(v);
}
};
template<>
struct switcher<-1> {
void run(int v){
}
};
调用switcher<50>::run( value );
,如果值为 0 到 50,prog<value>::run()
则调用。在prog::run
模板参数中是一个编译时间值。
可怕的黑客攻击,你可能会更好地使用另一种解决方案,但这是你所要求的。
这是一个基于 C++14 表的版本:
template<size_t N>
using index_t = std::integral_constant<size_t, N>; // C++14
template<size_t M>
struct magic_switch_t {
template<class F, class...Args>
using R=std::result_of_t<F(index_t<0>, Args...)>;
template<class F, class...Args>
R<F, Args...> operator()(F&& f, size_t i, Args&&...args)const{
if (i >= M)
throw i; // make a better way to return an error
return invoke(std::make_index_sequence<M>{}, std::forward<F>(f), i, std::forward<Args>(args)...);
}
private:
template<size_t...Is, class F, class...Args>
R<F, Args...> invoke(std::index_sequence<Is...>, F&&f, size_t i, Args&&...args)const {
using pF=decltype(std::addressof(f));
using call_func = R<F, Args...>(*)(pF pf, Args&&...args);
static const call_func table[M]={
[](pF pf, Args&&...args)->R<F, Args...>{
return std::forward<F>(*pf)(index_t<Is>{}, std::forward<Args>(args)...);
}...
};
return table[i](std::addressof(f), std::forward<Args>(args)...);
}
};
magic_switch_t<N>{}( f, 3, blah1, blah2, etc )
将调用f(index_t<3>{}, blah1, blah2, etc)
.
一些 C++14 编译器会阻塞包含 lambda 的可变包扩展。这不是必需的,您可以做一个解决方法,但解决方法很丑陋。
C++14 的特性都是可选的:你可以在 C++11 中实现它,但又是丑陋的。
传递的f
基本上应该是一个函数对象(一个auto
作为第一个参数的 lambda,或者一个手动的)。直接传递函数名不会很好,因为当第一个参数成为编译时值时,上面的方法最有效。
您可以使用 lambda 或函数对象包装函数模板以提供帮助。