Home > Software design >  How to call one of two C template functions with condition
How to call one of two C template functions with condition

Time:01-13

There is a class with two member template functions: fun1(), fun2(). I want to call one of the functions decided by a const bool class member : willCallFun1. There is a solution like fun() in the code, but the if-else branch will check every times while fun() is called. I want avoid branch. Since when the Foo object is constructed, const bool willCallFun1 has been set, so which function of fun1 and fun2 will be used can already be determined.

class Foo {
public:

  const bool willCallFun1;

  Foo(bool b) : willCallFun1{b}{
  }

  template<typename T>
  void fun1(T t) {
    std::cout << "fun1 "<< t << "\n";
  }

  template<typename T>
  void fun2(T t) {
    std::cout << "fun2 "<< t << "\n";
  }

  template<typename T>
  void fun(T t){
    if (willCallFun1) fun1<T>(t);
    else fun2<T>(t);
  }

};

int main() {
    Foo f1{true};
    f1.fun(123);
    f1.fun("hi");

    Foo f2{false};
    f2.fun(456);
    f2.fun("hello");
}

If fun1, fun2 are non-template functions, I can add a new member in the class, such as a function pointer or std::function to bind one of them at the constructor. I can't find a way to do it when they are template functions. I would be very grateful if someone could answer.

CodePudding user response:

Since you can't make willCallFun1 into a template parameter and use if constexpr to decide which function to call, you could create an array of member function pointers and lookup the correct one using willCallFun1 as an index variable.

template <typename T>
void fun(T t) {
    using fun_sig = void(Foo::*)(T);

    static constexpr fun_sig funs[] = {&Foo::fun2<T>, &Foo::fun1<T>};

    (this->*funs[willCallFun1])(t);
}

Demo

I'd test if this is actually faster than having a simple if though. I've done this before with disappointing results.

  • Related