Специализация шаблона c ++ на основе значения времени компиляции

Я медленно нащупываю свой путь к метапрограммированию шаблонов и не знаю, как реализовать следующее:

// 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>();

Во время компиляции я буду знать, какое значение перечисления имеет третий тип шаблона (инвариант времени компиляции), мертвый или живой. Можно ли определить два тела для функции Register, например:

// 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 ...  }

Я ознакомился с: Специализация шаблонов C ++ с постоянным значением

но я не мог понять, как применить это к этой ситуации.


person Short    schedule 22.05.2012    source источник


Ответы (2)


Функции шаблона не могут быть частично специализированы. Решение состоит в том, чтобы обернуть его структурой:

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();
}
person Pubby    schedule 22.05.2012
comment
Отлично работает! Спасибо, пабби - person Short; 22.05.2012

Уже поздно на вечеринку, но.

Способ сделать это, на мой взгляд, концептуально проще, а также легче читается, - это просто сделать разные значения вашего перечисления разными типами (внутри пространства имен, чтобы оно оставалось чистым) и воспользоваться преимуществом ( template) перегрузка функции:

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

Вы называете их так:

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