0

I have a vector container holding pointers of a base class:

class Wrapper_base {

public:
    virtual ~Wrapper_base() {}
};

template <typename T>
class Wrapper : public Wrapper_base {

private:
T t_;

public:

Wrapper(const T t) : t_(t) {}

};

Wrapper<int> a (1);
Wrapper<float> f = 2.0;
Wrapper<double> d = 3.1415;

vector<Wrapper_base*> w;

w.push_back(&a);
w.push_back(&f);
w.push_back(&d);

now, I am looking for a way to find the value wrapped by the Wrapper function. and the problem is I don't know what is the type of the derived class to down cast the base class pointer.

cout << ( (Wrapper<ReturnType?>) (w[0]) ) -> t_;

is there a way to achieve this? I don't want to check typeid value or use dynamic_cast because the design is supposed to support the general case and not a limited of number of types. I am also not looking for something like std::tuple or bost::tuple.

any suggestion?

Arash
  • 141
  • 10
  • Because the concrete derived type isn't known at compile time in the general case, you can't use that type anywhere a type is expected. – François Andrieux Oct 18 '17 at 18:12
  • is there any type of trick through template programming? – Arash Oct 18 '17 at 18:14
  • Template metaprogramming runs at compile time. Run-time information can't be taken into account. What you are asking would require the derived types to be known, in other words it falls back to using `std::tuple` or equivalent. – François Andrieux Oct 18 '17 at 18:15
  • In any case, you will need an instance of any code that would use this system for each possible derived type, which implies templating. If you are not limited in the number of possible derived types, the only practical way of doing this is to cause each new derived type to generate an new instance of the code you want to run. And the easiest way of doing that is to simply add a virtual member function. In all practical cases, the code that depends on the concrete type of your derived type will need to be templated in some way that depends on that type and instantiated for each derived type. – François Andrieux Oct 18 '17 at 18:19
  • Not sure, but maybe [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) can help you – 463035818_is_not_an_ai Oct 18 '17 at 19:18
  • virtual method or `variant, Wrapper >` ? – Jarod42 Oct 18 '17 at 20:50
  • how would a virtual method help? can u explain please? – Arash Oct 18 '17 at 22:30
  • Something like [that](https://ideone.com/CjZQow). [Visitor_pattern](https://en.wikipedia.org/wiki/Visitor_pattern) can complement that to avoid to pollute base class with too many methods (but then hierarchy should be known). – Jarod42 Oct 19 '17 at 12:18

1 Answers1

0

To answer the problem as stated in the question header, you often don't need to do that, you can use virtual methods instead.

To show how this helps with the issue in the body of the question of passing the right type to operator << you could:-

add a public friend function to Wrapper_base

friend std::ostream& operator<< (std::ostream& stream, const Wrapper_base& wb)
{
    wb.ToStream(stream);
    return stream;
}

and a pure virtual function virtual void ToStream(std::ostream& stream) const = 0;

(which can be private or public as you see fit)

in template class Wrapper, implement ToStream

virtual void ToStream(std::ostream& stream) const
{
    stream << t_;   
}

and then the following works

std::cout << *w[0] << ' ' << *w[1] << ' ' << *w[2];
ROX
  • 1,256
  • 8
  • 18
  • thanx but what if I want to call a non-polymorphic method? I guess , I need to do the right type casting. – Arash Oct 26 '17 at 01:40
  • I guess I don't understand what you're trying to achieve. Assuming you could do the cast, what were you expecting the code to uses that to look like? – ROX Oct 26 '17 at 09:39