简体   繁体   中英

c++ template specialization based on compile time value

I'm feeling my way into template meta-programming, slowly and I'm not sure how to implement the following:

// hpp file
enum MyEnum { Alive = 0, Dead };
class A {
    public:
        template<typename T, typename O, MyEnum ls>
        static int Register();
};

// elsewhere in the code...
A::Register<IType1, Type1, Dead>();

At compile time I will know what enum value the third template type is (compile-time invariant), either Dead or Alive. Is it possible to define two bodies for the Register function, something like:

// desired hpp file
template<typename T, typename O, Alive>
int Register();

template<typename T, typename O, Dead>
int Register();

// corresponding desired .inc file
template<typename T, typename O, Alive>
int Register() { // Alive specific implementation ...  }

template<typename T, typename O, Dead>
int Register() { // Dead specific implementation ...  }

I have taken a look at: C++ Template Specialization with Constant Value

but I have not been able to figure out how to make it apply to this situation.

Template functions can't be partially specialized. The solution is to wrap it in a struct:

template<typename T, typename O, MyEnum ls>
struct foo;

template<typename T, typename O>
struct foo <T, O, Alive> {
  static int Register() {
    // ...
  }
};

template<typename T, typename O>
struct foo <T, O, Dead> {
  static int Register() {
    // ...
  }
};

template<typename T, typename O, MyEnum ls>
int Register() {
  return foo<T, O, ls>::Register();
}

Very late to the party here, but.

A way to do this that I think is conceptually simpler and also easier to read is simply making the different values of your enum different types (inside a namespace, to keep it clean), and take advantage of (template) function overloading:

namespace State {
  struct Dead {};
  struct Alive {};
}

template<typename T, typename O>
int Register(State::Dead) {
   return 1;
}

template<typename T, typename O>
int Register(State::Alive) {
   return 2;
}

You call them like this:

int main() {
   Register<int,int>(State::Dead());
   Register<int,int>(State::Alive());
   return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM