malat
malat

Reputation: 12490

Partial class template specialization

I would like to add a member function in case the last template parameter of my class is explicitely set to a certain value. I do not understand how I can re-use code from previous definition.

Simplified example of what I would like to get compile:

template <int A, int B, int C>
struct S
{
  void fun() {}
};

template <int A, int B>
struct S<A,B,0>
{
  void fun1() {}
};

template <int A>
struct S<A,0,0>
{
  void fun2() {}
};

int main()
{
  S<0,0,0> s;
  s.fun();
  s.fun1();
  s.fun2();
  return 0;
}

I need to find a solution with C++03 compiler.

Upvotes: 2

Views: 475

Answers (1)

Andy Prowl
Andy Prowl

Reputation: 126412

As it is, your specialization is a non-specialization, because it does not specialize any of the primary template's arguments:

template<int A, int B>
struct S<A,B> // ...
//       ^^^
//       Does not really specialize the primary template,
//       no specialized pattern is introduced here

You could try rewriting it this way:

template<int A> // <== Only the first template parameter of the primary
                //     template is unconstrained in the pattern we want to
                //     express (the second template argument shall be 1)
struct S<A,1> : public S<A,0>
//       ^^^               ^
// Specializes!            Something meaningful should go here,
//                         but that actually depends on the real
//                         class templates you are using and their
//                         semantics
{
      void fun1() {}
};

As an alternative, if your goal is just to add one member function conditionally, you could use a SFINAE-constraint like the following instead of specialization:

#include <type_traits> // <== Required for std::enable_if<>

template <class T = void>
//                  ^^^^
//                  The function's return type here
typename std::enable_if<B == 1, T>::type
//                      ^^^^^^
//                      Your condition for the function's existence
fun1()
{
    // ...
}

Here is a live example demonstrating this technique.

Upvotes: 5

Related Questions