user3219492
user3219492

Reputation: 814

Non verbose solution to make a class member variable optional based on the type of template?

I want the class member variable only_if_int to be defined only if the class is instantiated with the template type int. I have a working solution, but it is too verbose.

#include <iostream>
#include <type_traits>

template<typename T, typename Enable = void>
class MyClass;

template<typename T>
class MyClass<T, std::enable_if_t<std::is_same<T, int>::value>>{
   public:
      int common;
      int only_if_int;

      MyClass()
      {
         common = 0;
         only_if_int = 0;
      }

      void alter_values()
      {
         common++;
         only_if_int++;
      }
};

template<typename T>
class MyClass<T, std::enable_if_t<!std::is_same<T, int>::value>>{
   public:
      int common;
      MyClass()
      {
         common = 0;
      }

      void alter_values()
      {
         common++;
      }
};

int main()
{
   MyClass<int>  int_class;
   MyClass<float>  float_class;
   int_class.alter_values();
   float_class.alter_values();

   std::cout<<"\n int_class "<<int_class.common<<"  "<<int_class.only_if_int;
   std::cout<<"\n int_class "<<float_class.common<<"  ";

   return 0;
}

In the above code, the templated class MyClass is defined twice(too much code duplicate). For eg: alter_values function is written twice. Is there a less verbose way, maybe with the help of constexpr std::is_same<T, int> or a different C++ feature to do the same thing?

Upvotes: 1

Views: 92

Answers (1)

cigien
cigien

Reputation: 60218

One approach would be to have a type that contains an int member only if it's instantiated with int, like this:

template<typename>
struct OnlyInt {};

template<>
struct OnlyInt<int> {
    int only_if_int;
};

Then MyClass can just inherit from this type:

template<typename T>
class MyClass : public OnlyInt<T> {
    public:
      int common;
      // ... contains only_if_int if T == int      
};

Now all uses of only_if_int will need to be wrapped in an if constexpr, and you have to use this-> to indicate that the member is from a base class. So for example:

only_if_int = 0;

becomes:

if constexpr (std::is_same_v<T, int>)
    this->only_if_int = 0;

etc.

Here's a demo.

Upvotes: 1

Related Questions