Hi all, I need to store in a class an object which type is within a predefined set. As I would like to avoid the overhead of virtual functions, I am wondering if variant could help me. Moreover, I would like to know what is the runtime cost of using such a type (instead of base class pointers), and the cost of the apply_visitor. Hope you could help. Regards, Olivier
AMDG Olivier Tournaire wrote:
I need to store in a class an object which type is within a predefined set. As I would like to avoid the overhead of virtual functions, I am wondering if variant could help me. Moreover, I would like to know what is the runtime cost of using such a type (instead of base class pointers), and the cost of the apply_visitor.
The cost is apply_visitor is approximately that of a switch statement. In Christ, Steven Watanabe
there is great disadvantage of variant in performance terms. One can't create instance of variant with proper type inside without calling copy costructor. Even if you want to create default constructed instance of a class, you need to call copy costructor. It's very bad for complex classes. On Sat, Apr 4, 2009 at 8:21 PM, Olivier Tournaire <olitour@gmail.com> wrote:
Thank you Steven,
On Sat, Apr 4, 2009 at 4:41 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG The cost is apply_visitor is approximately that of a switch statement.
Suppose I have 2 variant<type1,type2>. Is there something to help implementing a dispatcher ?
Regards,
Oivier
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
there is great disadvantage of variant in performance terms. One can't create instance of variant with proper type inside without calling copy costructor.
I think this depends on your compiler/optimizer. The following test code was compiled with MSVC9, release mode (/O2 /Ob2 /Oi /Ot /Oy /GL), see comments inside the code: int main() { struct A { A() : a_(1) {} int a_; }; struct B { B() : b_(2.0) {} double b_; }; struct Visitor : boost::static_visitor<> { void operator()(const A &a) const { std::cout << a.a_; } void operator()(const B &b) const { std::cout << b.b_; } void operator()(int i) const { std::cout << i; } void operator()(const std::string &s) const { std::cout << s; } }; B b; boost::variant<A, B> v(b); // the previous construction compiled into 1 instruction (even a call to the constructor was optimized out): // movsd xmm0,mmword ptr [__real@4000000000000000 (41FD68h)] boost::apply_visitor(Visitor(), v); std::string s = "abcd"; boost::variant<int, std::string> v1(s); // the previous construction compiled into a direct call to variant::make_initializer_node::initialize(), // which in turn calls basic_string::assing() - that's all. boost::apply_visitor(Visitor(), v1); }
In common case it is not compiller solution due to complexity of constructors/destructors of holded class. variant<A,B> v( B() ); this code MUST call constructor of class B two times. First time when B is created, second time when just created instance of B copyied to variant. Valid solution is use type-traits. Something like: variant<A,B> v( Trait<B>()) where Trait is empty class with typedefs On Tue, Apr 21, 2009 at 6:25 PM, Igor R<boost.lists@gmail.com> wrote:
there is great disadvantage of variant in performance terms. One can't create instance of variant with proper type inside without calling copy costructor.
I think this depends on your compiler/optimizer. The following test code was compiled with MSVC9, release mode (/O2 /Ob2 /Oi /Ot /Oy /GL), see comments inside the code:
int main() { struct A { A() : a_(1) {} int a_; }; struct B { B() : b_(2.0) {} double b_; }; struct Visitor : boost::static_visitor<> { void operator()(const A &a) const { std::cout << a.a_; } void operator()(const B &b) const { std::cout << b.b_; }
void operator()(int i) const { std::cout << i; } void operator()(const std::string &s) const { std::cout << s; } };
B b; boost::variant<A, B> v(b); // the previous construction compiled into 1 instruction (even a call to the constructor was optimized out): // movsd xmm0,mmword ptr [__real@4000000000000000 (41FD68h)]
boost::apply_visitor(Visitor(), v);
std::string s = "abcd";
boost::variant<int, std::string> v1(s); // the previous construction compiled into a direct call to variant::make_initializer_node::initialize(), // which in turn calls basic_string::assing() - that's all.
boost::apply_visitor(Visitor(), v1); } _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
2009/6/17 Maxim Koshelev <chuchelo@gmail.com>
In common case it is not compiller solution due to complexity of constructors/destructors of holded class.
variant<A,B> v( B() );
Note that this code does not create an instance of variant<A,B>, but declares a function.
this code MUST call constructor of class B two times. First time when B is created, second time when just created instance of B copyied to variant. Valid solution is use type-traits. Something like:
variant<A,B> v( Trait<B>())
Same here. Roman Perepelitsa.
participants (5)
-
Igor R
-
Maxim Koshelev
-
Olivier Tournaire
-
Roman Perepelitsa
-
Steven Watanabe