[Variant] C++11 variadic template implementation

Hi Boosters, I'd like to know if anybody were working on a C++11 version (using variadic templates) of Boost.Variant. I currently use the 'classic' version in my project, but since I need more-than-20-type variants, the compilation take a lot of time (extending the number of types that variant can support forces you to disable the use of precompiled headers). Plus, I'll need to use 70 type variants (MPL lists are physically limited to 50 types). If nobody has started to implement such a version yet, I'd be pleased to contribute. I've written an implementation. It's incomplete and far from perfect, but it could (hopefully) be a viable working basis.

On 15/04/12 11:57, Florian Goujeon wrote:
Hi Boosters,
I'd like to know if anybody were working on a C++11 version (using variadic
templates) of Boost.Variant.
Variadic templates would not help at all with Boost.Variant.
I've written an implementation.
Did you find a magic way to make a switch statement from a template parameter pack?

----- Original Message -----
From: Mathias Gaunard <mathias.gaunard@ens-lyon.org> To: boost@lists.boost.org Cc: Sent: Sunday, April 15, 2012 8:07 AM Subject: Re: [boost] [Variant] C++11 variadic template implementation
On 15/04/12 11:57, Florian Goujeon wrote:
Hi Boosters,
I'd like to know if anybody were working on a C++11 version (using variadic
templates) of Boost.Variant.
Variadic templates would not help at all with Boost.Variant.
I've written an implementation. Do you have the code posted online somewhere?
Did you find a magic way to make a switch statement from a template parameter pack?
Well you can expand the parameter pack to create a static array of function pointers. This is how it is done in this implementation: http://thenewcpp.wordpress.com/2012/02/15/variadic-templates-part-3-or-how-i... Thanks, Paul Fultz II

On 04/15/2012 03:02 PM, paul Fultz wrote:
Do you have the code posted online somewhere?
Yes I do: https://github.com/fgoujeon/scalpel/tree/master/src/scalpel/utility/variant This implementation is based on a fixed-size stack-based any container (any_container.hpp). I think it's annoying because it breaks the anti-aliasing rule. But I'll let you judge.

On 15/04/12 15:41, Florian Goujeon wrote:
On 04/15/2012 03:02 PM, paul Fultz wrote:
Do you have the code posted online somewhere?
Yes I do: https://github.com/fgoujeon/scalpel/tree/master/src/scalpel/utility/variant
This implementation is based on a fixed-size stack-based any container (any_container.hpp). I think it's annoying because it breaks the anti-aliasing rule. But I'll let you judge.
You use nested ifs, not as good as a switch. Also, the special code to deal with visitors that return void seems entirely unnecessary. As for any_container.hpp, the clear_and_set stuff (which I suppose you use in operator=) is very wrong. You're literally copying an object to a different location and calling the destructor there.

On 04/15/2012 04:26 PM, Mathias Gaunard wrote:
You use nested ifs, not as good as a switch.
Also, the special code to deal with visitors that return void seems entirely unnecessary.
As for any_container.hpp, the clear_and_set stuff (which I suppose you use in operator=) is very wrong. You're literally copying an object to a different location and calling the destructor there.
My implementation isn't perfect for sure. But is it fixable? Is it a good working basis? If you think so, I'll create a GIT repository right now so everyone can contribute. Or maybe we should base our work on Jarryd Beck's implementation (that Paul Fultz gave a link for).

on Sun Apr 15 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
On 15/04/12 15:02, paul Fultz wrote:
Well you can expand the parameter pack to create a static array of function pointers.
I see, interesting.
How does it fare in terms of bloat and performance? Are compilers still able to inline with this?
You can probably get somewhere by using constexpr to ensure that function pointers remain compile-time constants. However, note that such a dispatch may still be less efficient than a switch statement or chained if/then/else. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 04/15/12 08:02, paul Fultz wrote:
----- Original Message -----
From: Mathias Gaunard <mathias.gaunard@ens-lyon.org>
[snip]
Did you find a magic way to make a switch statement from a template parameter pack?
Well you can expand the parameter pack to create a static array of function pointers. This is how it is done in this implementation:
http://thenewcpp.wordpress.com/2012/02/15/variadic-templates-part-3-or-how-i...
[snip] IIUC, something similar was proposed earlier; however, a preprocessor generated switch statement was deemed faster: http://article.gmane.org/gmane.comp.lib.boost.devel/169739 However, maybe compiler's have improved since then. HTH. -regards, Larry

On 04/15/12 14:06, Larry Evans wrote:
On 04/15/12 08:02, paul Fultz wrote:
----- Original Message -----
From: Mathias Gaunard <mathias.gaunard@ens-lyon.org>
[snip]
Did you find a magic way to make a switch statement from a template parameter pack?
Well you can expand the parameter pack to create a static array of function pointers. This is how it is done in this implementation:
http://thenewcpp.wordpress.com/2012/02/15/variadic-templates-part-3-or-how-i...
[snip]
IIUC, something similar was proposed earlier; however, a preprocessor generated switch statement was deemed faster:
http://article.gmane.org/gmane.comp.lib.boost.devel/169739
However, maybe compiler's have improved since then.
Looking closer, I see that the gmane.comp.lib.boost.devel/169739 code did not use parameter pack expansion because it didn't use variadic templates; however, it did use a vector of function pointers. Also, apparently the switch library has an alternative implementation which does something similar here: http://svn.boost.org/svn/boost/sandbox/switch/libs/switch/alternate/switch/s... There's also, apparently, a test driver to compare the speed of alternative implementations here: http://svn.boost.org/svn/boost/sandbox/switch/libs/switch/alternate/switch/t... -regards, Larry

On 04/15/12 07:07, Mathias Gaunard wrote:
On 15/04/12 11:57, Florian Goujeon wrote:
Hi Boosters,
I'd like to know if anybody were working on a C++11 version (using variadic
templates) of Boost.Variant.
Variadic templates would not help at all with Boost.Variant.
Wouldn't variadic templates avoid one of the problems the OP mentioned: (extending the number of types that variant can support forces you to disable the use of precompiled headers). ? OTOH, it may be that using variadic templates would not lessen the compile time. Is that what you mean by "would not help"? -regards, Larry

On 15/04/12 21:17, Larry Evans wrote:
Wouldn't variadic templates avoid one of the problems the OP mentioned:
(extending the number of types that variant can support forces you to disable the use of precompiled headers).
? OTOH, it may be that using variadic templates would not lessen the compile time. Is that what you mean by "would not help"?
I was under the impression that Boost.Variant required a switch statement, that cannot be generated by variadic templates.

Mathias Gaunard-2 wrote
On 15/04/12 11:57, Florian Goujeon wrote:
Hi Boosters,
I'd like to know if anybody were working on a C++11 version (using variadic
templates) of Boost.Variant.
Variadic templates would not help at all with Boost.Variant.
I've written an implementation.
Did you find a magic way to make a switch statement from a template parameter pack?
Why not just use template partial specialization to explicitly expand the first N template arguments into a switch statement and recursively expand the remaining arguments in the default case if that fails? Something along the lines of recursive_apply <Args...>::apply(index) with the default case calling recursive_apply <Tail...>::apply(index-N) should suffice...is there some subtly I'm missing here? -- View this message in context: http://boost.2283326.n4.nabble.com/Variant-C-11-variadic-template-implementa... Sent from the Boost - Dev mailing list archive at Nabble.com.

On 04/15/12 04:57, Florian Goujeon wrote:
Hi Boosters,
I'd like to know if anybody were working on a C++11 version (using variadic
templates) of Boost.Variant.
I currently use the 'classic' version in my project, but since I need
more-than-20-type variants, the compilation take a lot of time (extending the
number of types that variant can support forces you to disable the use of
precompiled headers). Plus, I'll need to use 70 type variants (MPL lists are
physically limited to 50 types).
If nobody has started to implement such a version yet, I'd be pleased to
contribute.
I've written an implementation. It's incomplete and far from perfect, but it
could (hopefully) be a viable working basis.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
There's this: http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_st... which uses variadic templates; hence, doesn't have the limitations you mentioned about the number of bounded types. *HOWEVER* I'v not tested whether it takes more or less compile time than variant. One difference of one_of_maybe w.r.t. boost::variant is that it's a true tagged variant. IOW, it allows duplicates in the bounded types: http://www.boost.org/doc/libs/1_49_0/doc/html/variant/tutorial.html#variant.... For example: variant<int,int> is not allowed because variant<int,int> when assigned from an int: variant<int,int> ii; ii=int(999); wouldn't, IIRC, know which bounded type, the 1st int or the 2nd, was intended as the target. OTOH: container<tags::one_of_maybe,unsigned,int,int> ii; ii.inject<0>(999); would work because the tag (the template arg to inject member function), indicates which bounded type is intended. You might object that: ii = int(999); is less "user-friendly" than: ii.inject<0>(999); however, I thought making the structure more like the actual mathematical disjoint union: http://en.wikipedia.org/wiki/Disjoint_union was worth the extra trouble. In addition, one_of_maybe certainly doesn't have all the nice features of variant outlined here: http://www.boost.org/doc/libs/1_49_0/doc/html/variant.html#variant.abstract and in particular, it does not have: http://www.boost.org/doc/libs/1_49_0/doc/html/variant/design.html#variant.de... Instead, if one of the bounded types has not yet been injected, the which function will return a tag value indicating this and the user is required to check this. I thought this would be useful for implementing something like boost's optional, which would then be like one_of_maybe with just 1 bounded type. Tests for one_of_maybe (and other composite_storage types) are here: http://svn.boost.org/svn/boost/sandbox/variadic_templates/libs/composite_sto... HTH. -regards, Larry

On 04/15/12 04:57, Florian Goujeon wrote:
Hi Boosters,
I'd like to know if anybody were working on a C++11 version (using variadic
templates) of Boost.Variant.
I currently use the 'classic' version in my project, but since I need
more-than-20-type variants, the compilation take a lot of time (extending the
number of types that variant can support forces you to disable the use of
precompiled headers). Plus, I'll need to use 70 type variants (MPL lists are
physically limited to 50 types). [snip] There's this:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_st...
which uses variadic templates; hence, doesn't have the limitations you mentioned about the number of bounded types. [snip] OOPS. I failed to remember that container_one_of_maybe does use the
On 04/15/12 12:39, Larry Evans wrote: proposed switch library, which includes: http://svn.boost.org/svn/boost/sandbox/switch/boost/control/switch.hpp which does have these code lines: #ifndef BOOST_SWITCH_LIMIT #define BOOST_SWITCH_LIMIT 50 #endif #if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_REPEAT #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif #if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_ITERATION #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif which means container_one_of_maybe *does* have the limitations you were trying to avoid. Sorry for noise. I believe container_one_of_maybe could be modified to use the "static array of function pointers" method mentioned in another post to this thread, which was written by Paul Fultz: http://article.gmane.org/gmane.comp.lib.boost.devel/230073 The only reason that method was not tried in container_one_of_maybe was for reasons cited in my reply to Paul's post. -regards, Larry

There's this:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_st...
which uses variadic templates; hence, doesn't have the limitations you mentioned about the number of bounded types. [snip] OOPS. I failed to remember that container_one_of_maybe does use the proposed switch library, which includes:
http://svn.boost.org/svn/boost/sandbox/switch/boost/control/switch.hpp
which does have these code lines:
#ifndef BOOST_SWITCH_LIMIT #define BOOST_SWITCH_LIMIT 50 #endif
#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_REPEAT #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif #if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_ITERATION #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif
which means container_one_of_maybe *does* have the limitations you were trying to avoid.
Sorry for noise.
I believe container_one_of_maybe could be modified to use the "static array of function pointers" method mentioned in another post to this thread, which was written by Paul Fultz:
This is written by Jarryd Beck, not by me.
http://article.gmane.org/gmane.comp.lib.boost.devel/230073
The only reason that method was not tried in container_one_of_maybe was for reasons cited in my reply to Paul's post.

On 04/18/12 10:52, Larry Evans wrote:
On 04/15/12 04:57, Florian Goujeon wrote:
Hi Boosters,
I'd like to know if anybody were working on a C++11 version (using variadic
templates) of Boost.Variant.
I currently use the 'classic' version in my project, but since I need
more-than-20-type variants, the compilation take a lot of time (extending the
number of types that variant can support forces you to disable the use of
precompiled headers). Plus, I'll need to use 70 type variants (MPL lists are
physically limited to 50 types). [snip] There's this:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_st...
which uses variadic templates; hence, doesn't have the limitations you mentioned about the number of bounded types. [snip] OOPS. I failed to remember that container_one_of_maybe does use the
On 04/15/12 12:39, Larry Evans wrote: proposed switch library, which includes:
http://svn.boost.org/svn/boost/sandbox/switch/boost/control/switch.hpp
which does have these code lines:
#ifndef BOOST_SWITCH_LIMIT #define BOOST_SWITCH_LIMIT 50 #endif
#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_REPEAT #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif #if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_ITERATION #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit #endif
which means container_one_of_maybe *does* have the limitations you were trying to avoid.
Sorry for noise.
I believe container_one_of_maybe could be modified to use the "static array of function pointers" method mentioned in another post to this thread, which was written by Paul Fultz:
http://article.gmane.org/gmane.comp.lib.boost.devel/230073
The only reason that method was not tried in container_one_of_maybe was for reasons cited in my reply to Paul's post.
-regards, Larry
There's now an alternate implementation which uses the static array of function pointers and therefore does not suffer the limitation imposed by the BOOST_PP_LIMIT_* macros. You can switch between the two implementations by #define'ing or #undef the macro: LAYOUT_DOMAIN_CONTAINER_PACK This is used here: http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_st... When defined, the static array of function pointer is used; otherwise the switch_ method is used. It has been tested using: http://svn.boost.org/svn/boost/sandbox/variadic_templates/libs/composite_sto... HTH. -regards, Larry
participants (6)
-
Dave Abrahams
-
Florian Goujeon
-
Larry Evans
-
Mathias Gaunard
-
paul Fultz
-
sfields