假设我有以下形式的模板化函数:
template<bool a, bool b, bool c>
void foo(){
if(a) printf("I do something when a is true!\n");
if(b) printf("I do something when b is true!\n");
if(c) printf("I do something when c is true!\n");
}
现在我有了这个函数,可以为8种可能情况中的每种情况专门编译时间(a = b = c = true,a = b = true c = false等等)。
我想在运行时获得的a,b和c值调用此函数。
如果模板只有一个参数我可以做:
void caller(bool a){
if(a) foo<true>();
else foo<false>();
}
但是如果你有2个以上的参数怎么办?你不能只做:
void caller(bool a, bool b, bool c){
foo<a,b,c>();
}
如果你使用if-else / switch做这件事就会产生麻烦。 我想让编译器编译foo的8个版本,然后调用
foo<a,b,c>()
如果我有以下情况,可以采用相同的情况:
template<int a>
void foo(){
printf("%d", a);
}
说我知道a可以在0到32之间变化,即32。 我想做点什么:
void caller(int a){
if(a<=32 && a>0) foo<a>();
else printf("ERROR!/n");
}
处理这类情况的最佳方法是什么?
答案 0 :(得分:5)
但是如果你有2个以上的参数怎么办?你不能只做:
您可以使用可变参数模板,递归,高阶函数和std::integral_constant
:
template <typename TF>
auto with_bool_constant(TF xf)
{
return xf();
};
template <typename TF, typename T, typename... Ts>
auto with_bool_constant(TF xf, T x, Ts... xs)
{
if(x)
return with_bool_constant([&](auto... ys)
{ xf(std::integral_constant<bool, true>{}, ys...); },
xs...);
else
return with_bool_constant([&](auto... ys)
{ xf(std::integral_constant<bool, false>{}, ys...); },
xs...);
};
用法:
template <bool a, bool b, bool c>
void f()
{
std::cout << std::boolalpha << a << " " << b << " " << c << "\n";
}
int main()
{
auto f_wrapper = [](auto a, auto b, auto c)
{
return f<a, b, c>();
};
with_bool_constant(f_wrapper, true, false, true);
}
说我知道a可以在0和32之间变化,即32。我想做类似的事情:
您可以使用boost::hana::make_range
生成0...32
编译时范围(必须在编译时知道边界)。然后,您可以使用boost::hana::for_each
或类似的编译时迭代构造将运行时值转换为std::integral_constant<int, X>
,并将类似的技术应用于我上面发布的那个。
答案 1 :(得分:2)
你有正确的想法,你只需要对每个参数进行quasirecursly:
#include <cstdio>
template <bool a, bool b, bool c>
void foo() {
if(a) printf("I do something when a is true!\n");
if(b) printf("I do something when b is true!\n");
if(c) printf("I do something when c is true!\n");
}
template <bool... bs>
void caller() {
foo<bs...>();
}
template <bool... cbs, typename... RBS>
void caller(bool rb0, RBS... rbs) {
if (rb0) {
caller<cbs..., true>(rbs...);
} else {
caller<cbs..., false>(rbs...);
}
}
int main() {
caller(true, false, true);
}