0

My code:

enum class list{one, two};
template <list T> class Base;
template <> class Base <list::one>{
    A a{list::one};
    B b{list::one};
    C c{list::one};
};
template <> class Base <list::two>{
    B b{list::two};
    C c{list::two};
    D d{list::two};
};

But I would like to avoid duplicating code, and use reference to specialization value, like this:

template <> class Base <list::one>{
    A a{T};
    B b{T};
    C c{T};
};
template <> class Base <list::two>{
    B b{T};
    C c{T};
    D d{T};
};

I can make sludge temporary variable, but does not look good too:

template <> class Base <list::one>{
    list T = list::one;
    A a{T};
    B b{T};
    C c{T};
};

Is there are any way to get reference to template specialization value?

Enlico
  • 23,259
  • 6
  • 48
  • 102
LynXz
  • 78
  • 8
  • 2
    I'm afraid making the variable is the only option. Just make sure you add `static constexpr` to it so is will behave the same way as the template parameter. – Piotr Siupa Jan 07 '21 at 05:52

1 Answers1

3

In the following example I'm using SFINAE to make T available in the definition of Base. Specifically I have done the following:

  • added one dummy type parameter to the primary template,
  • made the two specialization partial by not specifying the parameter T (and specifying the second dummy type parameter),
  • specified the second dummy type parameter enforcing that T is equal to list::one and list::two in the two specializations, via std::enable_if_t.
#include <iostream>
#include <type_traits>

enum class list{one, two};

// to make the code compile
class A { public: A(list) {} };
class B { public: B(list) {} };
class C { public: C(list) {} };
class D { public: D(list) {} };

// primary template (second param's sole purpose is to allow partial spec.)
template <list T, typename = void>
class Base;

// partial specialization #1
template <list T>
class Base <T, std::enable_if_t<T == list::one>>{
    A a{T};
    B b{T};
    C c{T};
  public:
    Base() { std::cout << "list::one\n"; }
};

// partial specialization #2
template <list T>
class Base <T, std::enable_if_t<T == list::two>>{
    B b{T};
    C c{T};
    D d{T};
  public:
    Base() { std::cout << "list::two\n"; }
};

int main() {
    Base<list::one> o;
    Base<list::two> t;
}

This is a pretty standard way of using taking advantage of SFINAE via std::enable_if. Similar examples can be found on cppreference page on std::enable_if, where the last example (the one with the first comment // primary template) resambles the code above.

Enlico
  • 23,259
  • 6
  • 48
  • 102