robert
robert

Reputation: 2027

How to make a generic template C++ pointer?

Assume the snippet below. How can I make this compiling/working? I do not want to move print to the String/Float class, because in my real world situation this function is combining a lot of data.

So basically I want a pointer/member to "any type (in this case string/float)" then use it, and call dynamically something else (in this case print)?

I assume that this does not work (among others) because it cannot determine at compile time which type T of ptr will have at compile time.

What is the general pattern to solve such kind of problems?

#include <iostream>

template<typename T>
class AbstractClass {
   virtual T getValue()=0;
};

class StringClass : public AbstractClass<std::string> {
   std::string getValue() override {
      return "A";
   }
};

class FloatClass : public AbstractClass<float> {
   float getValue() override {
     return 1;
   }
};

class Processor {
   public:
   AbstractClass<T>* ptr;

   void doIt() {
     ptr=new StringClass();
     print(ptr->getValue());
     delete ptr;
     ptr=new FloatClass();
     print(ptr->getValue());
     delete ptr;
   }

   void print(std::string i) {
     std::cout << "String "<<i<<std::endl;
   }
   void print(float i) {
    std::cout << "Float "<<i<<std::endl;
   }
}

int main() {
   Processor a;
   a.doIt();
}

Upvotes: 0

Views: 70

Answers (1)

lorro
lorro

Reputation: 10880

If you want an object that's 'one of' a given set of types, you can use std::variant<Ts...>. Mathematically, it represents discriminated/tagged union. This way, you don't need a pointer, neither a base class. Example:

#include <iostream>
#include <variant>

class StringClass {
   std::string getValue() override {
      return "A";
   }
};

class FloatClass {
   float getValue() override {
     return 1;
   }
};

using ClassWithGetValue = std::variant<StringClass, FloatClass>;

class Processor {
   public:
   ClassWithGetValue v;

   void doIt() {
     v = StringClass();
     std::visit([&](auto&& v1) {
       print(v1.getValue());
     });
     v = FloatClass();
     std::visit([&](auto&& v1) {
       print(v1.getValue());
     });
   }

   void print(std::string i) {
     std::cout << "String "<<i<<std::endl;
   }
   void print(float i) {
    std::cout << "Float "<<i<<std::endl;
   }
}

int main() {
   Processor a;
   a.doIt();
}

Upvotes: 1

Related Questions