variant: bounded types derive from same base class

Hello, I have a library with an abstract base class ABC and derived classes D1... Dn. These classes cannot be changed. User code wants to write code that depends on which concrete type the object being passed. User writes: void f( const ABC& abc ) { Tag t = abc.GetTag() ; // Tag is an enum for all the derived types, delivered by the lib Switch (t) { case: case: case: } } /// SO ugly, nevertheless if some case is missing, g++ for e.g. prints warnings I am told this is the visitor pattern I then looked at boost::variant<> The lib could deliver typedef boost::variant<D1, ... , Dn> ABCDerived; and the user could write visitors to visit ABCDerived objects, here the user is enforced to implement all cases in the visitor. but then the function f expects ABC objects. Can I still do: void f( const ABC& abc ) { // how to write code to use the visitors with abc ? } Rds,

typedef boost::variant<D1, ... , Dn> ABCDerived;
and the user could write visitors to visit ABCDerived objects, here the user is enforced to implement all cases in the visitor.
but then the function f expects ABC objects. Can I still do:
void f( const ABC& abc ) { // how to write code to use the visitors with abc ? }
struct YourVisitor : boost::static_visitor<functor return type> { result_type operator()(const D1 &d1) {...} result_type operator()(const D2 &d1) {...} // etc. for all the type in the variant }; then: boost::apply_visitor(YourVisitor(), yourVariant);

Hi! With variant you don't need the base class at all. Usually you know in the context of your app, which object should be there. In that case you implement the generic visitor: struct my_visitor { typedef result_type void; template<class T> result_type operator()(T const& all_other) { // this is usually an error, because this type is unexpected in the current context } result_type operator()(ABCDerived1 const& derived1) { // handle derived1 here } result_type operator()(ABCDerived2 const& derived2) { // handle derived2 here } ... result_type operator()(ABCDerivedN const& derivedN) { // handle derived2 here } }; You can also work with template specialization and define specialized operator() in place where the ABCDerivedN is known. Hope that helps, Ovanes On Mon, Aug 3, 2009 at 2:35 PM, Hicham Mouline <hicham@mouline.org> wrote:
Hello,
I have a library with an abstract base class ABC and derived classes D1... Dn. These classes cannot be changed.
User code wants to write code that depends on which concrete type the object being passed.
User writes:
void f( const ABC& abc ) { Tag t = abc.GetTag() ; // Tag is an enum for all the derived types, delivered by the lib Switch (t) { case: case: case: } } /// SO ugly, nevertheless if some case is missing, g++ for e.g. prints warnings
I am told this is the visitor pattern
I then looked at boost::variant<>
The lib could deliver
typedef boost::variant<D1, ... , Dn> ABCDerived;
and the user could write visitors to visit ABCDerived objects, here the user is enforced to implement all cases in the visitor.
but then the function f expects ABC objects. Can I still do:
void f( const ABC& abc ) { // how to write code to use the visitors with abc ? }
Rds,
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Behalf Of Ovanes Markarian On behalf of; Igor R [boost.lists@gmail.com] ---------------------------------------------------------------------------- ------------------- Thank you for your answers, But it may be boost::variant is not what I need, but perhaps a different facility implementing visitor pattern. My restriction is that f takes a ABC const-ref as an input. Can I construct the variant from the const ABC& abc Maybe like variant<D1, D2, ... Dn> v(abc); without deep copying. The Di objects are big. Then I would apply the visitation. Maybe storing variant<D1*, D2*, Dn*>... So f would look like void f( const ABC& abc ) { const VariantTypeDefProvidedByLib v(&abc); v.apply_visitor( YourVisitor ); } If this works, what is its cost relative to having been able to simply implement virtual functions in ABC? Again, thanks for the answers, Regards,

My restriction is that f takes a ABC const-ref as an input. Can I construct the variant from the const ABC& abc Maybe like variant<D1, D2, ... Dn> v(abc);
without deep copying. The Di objects are big.
Then I would apply the visitation.
Maybe storing variant<D1*, D2*, Dn*>...
Yes, you can store ptrs in the variant.
So f would look like
void f( const ABC& abc ) { const VariantTypeDefProvidedByLib v(&abc);
v.apply_visitor( YourVisitor ); }
You cannot construct the variant in f(), because you already lost the compile-time type of the object - it's ABC now. If you'd like to work with ABC's and virtual functions, then why do you need variant? Variant is about preserving the compile-time type.

-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Igor R Sent: 03 August 2009 14:50 To: boost-users@lists.boost.org Subject: Re: [Boost-users] variant: bounded types derive from same base class
My restriction is that f takes a ABC const-ref as an input. Can I construct the variant from the const ABC& abc Maybe like variant<D1, D2, ... Dn> v(abc);
without deep copying. The Di objects are big.
Then I would apply the visitation.
Maybe storing variant<D1*, D2*, Dn*>...
Yes, you can store ptrs in the variant.
So f would look like
void f( const ABC& abc ) { const VariantTypeDefProvidedByLib v(&abc);
v.apply_visitor( YourVisitor ); }
You cannot construct the variant in f(), because you already lost the compile-time type of the object - it's ABC now. If you'd like to work with ABC's and virtual functions, then why do you need variant? Variant is about preserving the compile-time type.
Then that's not what I need. I need a runtime visitor pattern. Parts of the user code deal with ABCs, and the user also writes functions for specific derived types, that use non common public functions of the derived types. The f function still needs to dispatch to the appropriate piece of code depending on the ABC type. void f( const ABC& abc ) { Switch (abc.getTag()) { case D1tag: // do something ... Case Dntag: } } // I get the warning from g++ if I miss 1 case Or void f( const ABC& abc ) { if (dynamic_cast<D1*>(&abc)) // do something ... if (dynamic_cast<Dn*>(&abc)) // do something } // no warnings here If I miss a case Maybe what I want is just not possible,

Hi! The only solution I can come up with is the declaration of the visitor in your ABCBase as virtual function and visitor has a function template to dispatch different types: class ABCVisitor { public: template<class T> void visit(T& t) { // no visit implemented ... } }; class ABCBase { //... dtor, copy ctor, assignment operator etc. public: void accept_visitor(ABCVisitor& v) { do_accept_visitor(v); } private: virtual void accept_visitor(ABCVisitor& v)=0; }; class ABCDerived1 { //... dtor, copy ctor, assignment operator etc. void accept_visitor(ABCVisitor& v) { v.visit(*this); } }; template<> void ABCVisitor::visit<ABCDerived1>(ABCDerived1& derived) { // handle derived here... } Hope that helps, Ovanes On Mon, Aug 3, 2009 at 4:22 PM, Hicham Mouline <hicham@mouline.org> wrote:
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Igor R Sent: 03 August 2009 14:50 To: boost-users@lists.boost.org Subject: Re: [Boost-users] variant: bounded types derive from same base class
My restriction is that f takes a ABC const-ref as an input. Can I construct the variant from the const ABC& abc Maybe like variant<D1, D2, ... Dn> v(abc);
without deep copying. The Di objects are big.
Then I would apply the visitation.
Maybe storing variant<D1*, D2*, Dn*>...
Yes, you can store ptrs in the variant.
So f would look like
void f( const ABC& abc ) { const VariantTypeDefProvidedByLib v(&abc);
v.apply_visitor( YourVisitor ); }
You cannot construct the variant in f(), because you already lost the compile-time type of the object - it's ABC now. If you'd like to work with ABC's and virtual functions, then why do you need variant? Variant is about preserving the compile-time type.
Then that's not what I need. I need a runtime visitor pattern.
Parts of the user code deal with ABCs, and the user also writes functions for specific derived types, that use non common public functions of the derived types.
The f function still needs to dispatch to the appropriate piece of code depending on the ABC type.
void f( const ABC& abc ) {
Switch (abc.getTag()) { case D1tag: // do something ... Case Dntag: } } // I get the warning from g++ if I miss 1 case
Or
void f( const ABC& abc ) { if (dynamic_cast<D1*>(&abc)) // do something ... if (dynamic_cast<Dn*>(&abc)) // do something } // no warnings here If I miss a case
Maybe what I want is just not possible,
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

sorry, forgot to derive ABCDerived1 form ABCBase ;) But hope you got the intention. On Mon, Aug 3, 2009 at 5:33 PM, Ovanes Markarian <om_boost@keywallet.com>wrote:
Hi!
The only solution I can come up with is the declaration of the visitor in your ABCBase as virtual function and visitor has a function template to dispatch different types:
class ABCVisitor { public: template<class T> void visit(T& t) { // no visit implemented ... } };
class ABCBase { //... dtor, copy ctor, assignment operator etc.
public: void accept_visitor(ABCVisitor& v) { do_accept_visitor(v); }
private: virtual void accept_visitor(ABCVisitor& v)=0; };
class ABCDerived1 : public ABCBase { //... dtor, copy ctor, assignment operator etc. void accept_visitor(ABCVisitor& v) { v.visit(*this); } };
template<> void ABCVisitor::visit<ABCDerived1>(ABCDerived1& derived) { // handle derived here... }
Hope that helps, Ovanes

From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Ovanes Markarian Sent: 03 August 2009 18:32 To: boost-users@lists.boost.org Subject: Re: [Boost-users] variant: bounded types derive from same base class sorry, forgot to derive ABCDerived1 form ABCBase ;) But hope you got the intention. On Mon, Aug 3, 2009 at 5:33 PM, Ovanes Markarian <om_boost@keywallet.com> wrote: Hi! The only solution I can come up with is the declaration of the visitor in your ABCBase as virtual function and visitor has a function template to dispatch different types: class ABCVisitor { public: template<class T> void visit(T& t) { // no visit implemented ... } }; class ABCBase { //... dtor, copy ctor, assignment operator etc. public: void accept_visitor(ABCVisitor& v) { do_accept_visitor(v); } private: virtual void accept_visitor(ABCVisitor& v)=0; }; class ABCDerived1 : public ABCBase { //... dtor, copy ctor, assignment operator etc. void accept_visitor(ABCVisitor& v) { v.visit(*this); } }; template<> void ABCVisitor::visit<ABCDerived1>(ABCDerived1& derived) { // handle derived here... } Hope that helps, Ovanes ---------------------------------------------------------------------------- ----------------- Unfortunately, that would require changing the ABCBase to add those 2 member functions. I can't touch ABCBase nor Really, I have an existing hierarchy of classes which I cannot touch, but I still would like to have "external" polymorphism behaviour without the need to add base class virtual functions. Rds,
participants (3)
-
Hicham Mouline
-
Igor R
-
Ovanes Markarian