2

I have a class template:

template<typename T>
struct DefaultPattern {
  using type = int;
  static int CalculateValue(const T& input) {
    return 0;
  }
};

For each type T, I will have a specialization. The problem is that in the specialization class, I need to define all the member variables and methods that are defined in the DefaultPattern, even though it is possible that they have the same value as the one in DefaultPattern. Here is an example:

// A specialization for int.
template<>
struct DefaultPattern<int> {
  // Same as DefaultPattern but I need to define it again.
  using type = int;
  static int CalculateValue(const int& input) {
    return input + 2;
  }
};

Is there a way so that when I do the specialization, I only need to define those members that are different from DefaultPattern?

max66
  • 65,235
  • 10
  • 71
  • 111
ZigZagZebra
  • 1,349
  • 3
  • 14
  • 25
  • Unrelated, but why `using type = int;` ? You never use `type` anywhere. – Jesper Juhl Apr 27 '18 at 15:33
  • @JesperJuhl It makes it easy to know the type given in situations like `decltype(foo)::type;` or other cases where the template argument isn't immediately obvious. Like how `std::vector::value_type` is always `T`. – François Andrieux Apr 27 '18 at 15:34
  • It is just an example that I simplified from real code. I can call DefaultPattern::type or DefaultPattern::type from another class. The variable type does not need to be the T we specialized. – ZigZagZebra Apr 27 '18 at 15:35
  • 2
    The specialization is a separate type, so doesn't "inherit" anything. You *could* have a common base class containing things that are always the same. – Bo Persson Apr 27 '18 at 15:45
  • Looks like it's a job for [CRTP](https://stackoverflow.com/questions/4173254/what-is-the-curiously-recurring-template-pattern-crtp). – O'Neil Apr 27 '18 at 16:19

1 Answers1

2

Is there a way so that when I do the specialization, I only need to define those members that are different from DefaultPattern?

A possible solution is a sort of self-inheritance: your specialization can inherit form the generic template. Note that to inherit from the generic template, the specilization uses a particular instantiation (e.g. T = long is used below).

For example:

template <>
struct DefaultPattern<int> : public DefaultPattern<long>
 {
   static int CalculateValue (int const & input)
    { return input + 2; }
 };

So DefaultPattern<int> inherit type = int from DefaulPattern<long> (or DefaultPattern<std::string> or something else) and redefine CalculateValue()

The following is a full working example:

#include <iostream>
#include <type_traits>

template <typename T>
struct DefaultPattern
 {
   using type = int;

   static int CalculateValue (T const &)
    { return 0; }
 };

template <>
struct DefaultPattern<int> : public DefaultPattern<long>
 {
   static int CalculateValue (int const & input)
    { return input + 2; }
 };

int main ()
 {
   static_assert( std::is_same<DefaultPattern<int>::type, int>{}, "!" );

   std::cout << DefaultPattern<long>::CalculateValue(1L) << std::endl;
   std::cout << DefaultPattern<int>::CalculateValue(1) << std::endl;
 }
iglesias
  • 57
  • 11
max66
  • 65,235
  • 10
  • 71
  • 111