处理2+模板参数的最佳方法是什么?

时间:2017-02-01 16:36:33

标签: c++ templates

假设我有以下形式的模板化函数:

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");
}

处理这类情况的最佳方法是什么?

2 个答案:

答案 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);
}

wandbox example

  

说我知道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);
}