I am trying to solve a programming problem that consists of an object (call it Diagram), that contains several parameters. Each parameter (the Parameter class) can be one of several types: int, double, complex, string - to name a few.
So my first instinct was to define my Diagram class as having a vector of template parameters, which would look like this.
class Diagram { private: std::vector<Parameter<T> > v; };
This doesn't compile, and I understand why. So, based on the recommendations on this page How to declare data members that are objects of any type in a class, I modified my code to look like:
class ParameterBase { public: virtual void setValue() = 0; virtual ~ParameterBase() { } }; template <typename T> class Parameter : public ParameterBase { public: void setValue() // I want this to be // void setValue(const T & val) { // I want this to be // value = val; } private: T value; }; class Diagram { public: std::vector<ParameterBase *> v; int type; };
I'm having trouble figuring out how to call the setValue function with an appropriate templated parameter. It is not possible to have a templated parameter in the ParameterBase abstract base class. Any help is greatly appreciated.
P.S. I don't have the flexibility to use boost::any.
A variable template may be introduced by a template declaration at namespace scope, where variable-declaration declares a variable. When used at class scope, variable template declares a static data member template.
Member functions can be function templates in several contexts. All functions of class templates are generic but are not referred to as member templates or member function templates. If these member functions take their own template arguments, they are considered to be member function templates.
No, template member functions cannot be virtual.
A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.
You got very close. I added a few bits because they're handy
class ParameterBase { public: virtual ~ParameterBase() {} template<class T> const T& get() const; //to be implimented after Parameter template<class T, class U> void setValue(const U& rhs); //to be implimented after Parameter }; template <typename T> class Parameter : public ParameterBase { public: Parameter(const T& rhs) :value(rhs) {} const T& get() const {return value;} void setValue(const T& rhs) {value=rhs;} private: T value; }; //Here's the trick: dynamic_cast rather than virtual template<class T> const T& ParameterBase::get() const { return dynamic_cast<const Parameter<T>&>(*this).get(); } template<class T, class U> void ParameterBase::setValue(const U& rhs) { return dynamic_cast<Parameter<T>&>(*this).setValue(rhs); } class Diagram { public: std::vector<ParameterBase*> v; int type; };
Diagram can then do stuff like these:
Parameter<std::string> p1("Hello"); v.push_back(&p1); std::cout << v[0]->get<std::string>(); //read the string v[0]->set<std::string>("BANANA"); //set the string to something else v[0]->get<int>(); //throws a std::bad_cast exception
It looks like your intent is to store resource-owning pointers in the vector. If so, be careful to make Diagram
have the correct destructor, and make it non-copy-constructable, and non-copy-assignable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With