c++ - Automatic downcast of a pointer to a derived object -


good morning,

i have templatized class , want manipulate objects vector of pointers. use vector of pointers templatized class need class derived non-templatized class, , did it.

here's problem: call method of derived class pointer base class, cannot use virtual functions because template functions can't made virtual. need make explicit cast, tedious: once create number object new, in fact, downcast need made number*, although object known number in advance.

i solved problem in awkward way: function myset tests supported values of typeid correct dynamic cast. long series of nested ifs perform typeid checking.

besides tediousness, function works calling 'set' method, , similar functions should defined calling other methods. if make automatic casting kind of object i'm pointing to, simpler.

the cons of approach are:

  1. the code repetitive: if defined function (such t get() {return val;}, need myget function full set of nested ifs!
  2. the list of supported types must explicitly defined nesting if calls
  3. the code may inefficient

the compiler knows lst[0] (in code below) points number object, although lst vector of element objects number<> objects derived.

is there method automatically downcast pointer defined base* pointer object pointed at?

if had correct downcasting, define thousands of methods in number<> class , call them propercasting -> function(...) call

here's code (it works properly, core definition of "myset")

thanks in advance, pietro m.

ps i'm interested in standard c++ approach without using other libraries except stl, such boost.

#include <iostream> #include <vector> #include <typeinfo>  using namespace std;  class element { public:     virtual void print() = 0; // print not templatized , works     //template <class t> virtual set(t v) = 0; // solve problems, if legal. };  template <class t> class number : public element {     t val; public:     void print() {cout << "number " << val << endl;}     void set(t v) {val = v;} };  // that's best can do! template <class t> void myset(t v, element *ptr) {     // there kink in template: compiler checks t type value of v, in case integer:     // cout << "type name template is: " << typeid(t).name() << endl;     // cout << "type name integer is:   " << typeid(int).name() << endl;      if (typeid(*ptr) == typeid(number<double>))     {         ((number<double> *) ptr) -> set(7);         return;     }     else if (typeid(*ptr) == typeid(number<float>))     {         ((number<float> *) ptr) -> set(7);         return;     }     // add other types... (tedious)     else     {         cout << "type not supported" << endl;     } }  int main() {     vector <element *> lst; // list of heterogeneous templatized objects     lst.push_back(new number<float>);     lst.push_back(new number<double>);      lst[0] -> print();      //((number<float> *) lst[0]) -> set(7); it's correct requires know type when call (tedious)      myset(7, lst[0]); // may inefficient, works (for types explicitly supported)      // cast_to_what_the_pointer_actually_points_to <lst[0]> -> set(7); // that's i'd do: downcast function checks object type , returns correct pointer able call class method...      lst[0] -> print(); } 

you're there. need have templated set method calls private virtual method typeid , void * pointer argument, allowing override decide how handle it:

class element {     virtual void set_impl(const std::type_info &, const void *) = 0; public:     template <class t> void set(t v) { set_impl(typeid(v), &v); } }; 

and example of how write set_impl:

template <class t> class number : public element {     t val;     void set_impl(const std::type_info &ti, const void *pv) {         if (ti == typeid(t)) {             val = *static_cast<const t *>(pv);         } else {             throw std::invalid_argument("incorrect type set()");         }     } }; 

this similar approach taken boost.any.


Comments

Popular posts from this blog

html5 - What is breaking my page when printing? -

html - Unable to style the color of bullets in a list -

c# - must be a non-abstract type with a public parameterless constructor in redis -