
I find myself creating this class member: compressed_pair< storage , compressed_pair< Lookup , compressed_pair< GetUnstored , SetUnstored > > > members; I imagine this sort of usage is pretty common. The problem is that it's hard to initialize this member efficiently: you have to build and copy too many compressed_pairs. I propose to extend compressed_pair with overloaded ctors, as follows: compressed_pair( first_param_type f , typename second_type::first_param_type sf , typename second_type::second_param_type ss); compressed_pair( first_param_type f , typename second_type::first_param_type sf , typename second_type::second_type::first_param_type ssf , typename second_type::second_type::second_param_type sss ); ... etc. If SFINAE doesn't take out these declarations when the second type is not a (compressed_)pair, we can always template them. Thoughts? -- Dave Abrahams Boost Consulting www.boost-consulting.com

On 5/18/06, David Abrahams <dave@boost-consulting.com> wrote: I imagine this sort of usage is pretty common. The problem is that it's hard to initialize this member efficiently: you have to build and copy too many compressed_pairs. I propose to extend compressed_pair with overloaded ctors, as follows: compressed_pair( first_param_type f , typename second_type::first_param_type sf , typename second_type::second_param_type ss); compressed_pair( first_param_type f , typename second_type::first_param_type sf , typename second_type::second_type::first_param_type ssf , typename second_type::second_type::second_param_type sss ); ... etc. If SFINAE doesn't take out these declarations when the second type is not a (compressed_)pair, we can always template them. ________ SFINAE would not come into play with just overloaded constructors, regardless of the fact that they are constructors of a template instantiation. The constructors would have to be templates themselves. Correct me if I'm missing something, but would it not be better to just have a compressed_tuple template, or are there reasons I am missing? -- -Matt Calabrese

On May 18, 2006, at 5:14 PM, Matt Calabrese wrote:
SFINAE would not come into play with just overloaded constructors, regardless of the fact that they are constructors of a template instantiation. The constructors would have to be templates themselves. Correct me if I'm missing something, but would it not be better to just have a compressed_tuple template, or are there reasons I am missing?
Actually you don't even need a new type compressed_tuple. You could put this functionality straight into tuple. It'd be a royal pain to do for tuple sizes greater than 3 or 4 though. Dave, how many empty members do you find yourself glomming together? I often have several potentially empty members but usually have at least that many non- empty members to spread them around on (I have one example where wanted to glom two empty members onto a non-empty member). -Howard

Howard Hinnant wrote:
On May 18, 2006, at 5:14 PM, Matt Calabrese wrote:
SFINAE would not come into play with just overloaded constructors, regardless of the fact that they are constructors of a template instantiation. The constructors would have to be templates themselves. Correct me if I'm missing something, but would it not be better to just have a compressed_tuple template, or are there reasons I am missing?
Actually you don't even need a new type compressed_tuple. You could put this functionality straight into tuple. It'd be a royal pain to do for tuple sizes greater than 3 or 4 though. Dave, how many empty members do you find yourself glomming together? I often have several potentially empty members but usually have at least that many non- empty members to spread them around on (I have one example where wanted to glom two empty members onto a non-empty member).
boost::bind( f, _1, _2, _3, _4, _5 ) has five empty members. :-)

On 5/18/06, Howard Hinnant <hinnant@twcny.rr.com> wrote: Actually you don't even need a new type compressed_tuple. You could put this functionality straight into tuple. It'd be a royal pain to do for tuple sizes greater than 3 or 4 though. Dave, how many empty members do you find yourself glomming together? I often have several potentially empty members but usually have at least that many non- empty members to spread them around on (I have one example where wanted to glom two empty members onto a non-empty member). True, though one [potential] problem with that would be that compressed pairs and tuples are allowed to share storage for empty types, whereas a regular tuple, as far as I know, currently allows users to assume a separate storage location for each element. This could pose a problem in the rare yet valid case that programmers compare pointers to the instances or if they use the address of the object as a unique identifier for the instance. Then again, I doubt that would impact much, if any users' code, so tuple could be adapted without much problem. Either way, I definately agree that some form of tuple with optimized storage would be a great addition to boost. -- -Matt Calabrese

Matt Calabrese wrote:
adapted without much problem. Either way, I definately agree that some form of tuple with optimized storage would be a great addition to boost.
Fusion! :)... Ok, it's not there yet... But if/when it gets accepted, we'll definitely have optimized storage for fusion::cons/list. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Well, I was bored so I put together a simple compressed_tuple anyway as an example of how it could be implemented fairly elegantly and account for a large number of elements. Right now it's set to work with up to 10 elements, but that can be adjusted by modifying the #define at the top. The difference from compressed pair is that storage is not shared if two types are used that are the same empty type. A get member function template is supported, but not a non-member version, though one could be easily added. http://www.illegal-immigration.com/Riv/boost/compressed_tuple.hpp -- -Matt Calabrese

"Matt Calabrese" <rivorus@gmail.com> writes:
Well, I was bored so I put together a simple compressed_tuple anyway as an example of how it could be implemented fairly elegantly and account for a large number of elements. Right now it's set to work with up to 10 elements, but that can be adjusted by modifying the #define at the top. The difference from compressed pair is that storage is not shared if two types are used that are the same empty type. A get member function template is supported, but not a non-member version, though one could be easily added.
http://www.illegal-immigration.com/Riv/boost/compressed_tuple.hpp
Ouch! Are you sure you wouldn't rather use file iteration for that? http://boost-consulting.com/mplbook/preprocessor.html#file-iteration -- Dave Abrahams Boost Consulting www.boost-consulting.com

"Matt Calabrese" <rivorus@gmail.com> writes:
On 5/18/06, Howard Hinnant <hinnant@twcny.rr.com> wrote: Actually you don't even need a new type compressed_tuple. You could put this functionality straight into tuple. It'd be a royal pain to do for tuple sizes greater than 3 or 4 though. Dave, how many empty members do you find yourself glomming together? I often have several potentially empty members but usually have at least that many non- empty members to spread them around on (I have one example where wanted to glom two empty members onto a non-empty member).
True, though one [potential] problem with that would be that compressed pairs and tuples are allowed to share storage for empty types,
I don't think so. See line 258 of http://www.boost-consulting.com/boost/boost/detail/compressed_pair.hpp -- Dave Abrahams Boost Consulting www.boost-consulting.com

On 5/19/06, David Abrahams <dave@boost-consulting.com> wrote: I don't think so. See line 258 of http://www.boost-consulting.com/boost/boost/detail/compressed_pair.hpp Oh, that's better. 1.33's comments were not updated after the change and I trusted the comment without checking implementation: http://boost.org/boost/detail/compressed_pair.hpp Note that even though the implementation does use separate storage, the comment says it is shared. -- -Matt Calabrese

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uves3axtp.fsf@boost-consulting.com...
I find myself creating this class member:
compressed_pair< storage , compressed_pair< Lookup , compressed_pair< GetUnstored , SetUnstored > > > members;
I imagine this sort of usage is pretty common. The problem is that it's hard to initialize this member efficiently: you have to build and copy too many compressed_pairs. I propose to extend compressed_pair with overloaded ctors, as follows:
compressed_pair( first_param_type f , typename second_type::first_param_type sf , typename second_type::second_param_type ss);
compressed_pair( first_param_type f , typename second_type::first_param_type sf , typename second_type::second_type::first_param_type ssf , typename second_type::second_type::second_param_type sss );
...
etc.
If SFINAE doesn't take out these declarations when the second type is not a (compressed_)pair, we can always template them.
Thoughts?
The first thought that comes to my mind is that this situation cries out for a compressed_tuple class. How difficult would it be to write one? Joe Gottman

David Abrahams wrote:
I find myself creating this class member:
compressed_pair< storage , compressed_pair< Lookup , compressed_pair< GetUnstored , SetUnstored > > > members;
Just one comment here: shouldn't the storage member be in the innermost compressed_pair? Currently the innermost item compressed_pair<GetUnsorted, SetUnsorted> has two empty members and so isn't actually "compressed". Using: compressed_pair< empty1, compressed_pair< empty2, compressed_pair< empty3, storage> > > ensures that each compressed pair has one non-empty member and one empty member, so the final object should be just sizeof(storage). All of which suggests that a compressed-tuple would be a good idea, although ordering the items within the tuple to ensure compression is actually a larger challenge than folks may have realised. In the mean time if additional template constructors can be added, I see no problem with that. John.

"John Maddock" <john@johnmaddock.co.uk> writes:
All of which suggests that a compressed-tuple would be a good idea, although ordering the items within the tuple to ensure compression is actually a larger challenge than folks may have realised.
Actually I think this is pretty easy. Here's the sketch: struct empty {}; template <class Key, class Value, class Tail = empty> struct node : Tail { // typical associative lookup tricks using overloading, per // Boost.Parameter library, or, I'm sure, Fusion's map }; template < class Types // MPL sequence , class Keys // types by which we'll do lookup
struct compressed_tuple_base { typedef typename mpl::sort< mpl::zip_view<Types,Keys> , mpl::less<is_empty<mpl::first<_1> >, is_empty<mpl::first<_2> > > >::type sorted_pairs; typedef typename mpl::fold< sorted_pairs , node<mpl::second<_2>, mpl::first<_2>, _1> , empty >::type type; }; template < class Types // MPL sequence , class Keys = mpl::range_c<int, 0, mpl::size<Types>::value>
struct compressed_tuple : compressed_tuple_base<Types,Keys>::type { // ctors // The easy ctor will initialize from a tuple of references, // which we can build using tie() ... // get<N> just does lookup with integral_c<int,N> as the key };
In the mean time if additional template constructors can be added, I see no problem with that.
I think I'll code it with fusion when I get a moment :). -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (7)
-
David Abrahams
-
Howard Hinnant
-
Joe Gottman
-
Joel de Guzman
-
John Maddock
-
Matt Calabrese
-
Peter Dimov