
On 11/05/10 13:01, Robert Lupton the Good wrote:
I was very excited to find the boost::fusion library, expecting that I could use it to implement structs with introspection. I still think I can, but I was disappointed to see that I'm paying a size penalty. I'd have expected all the book-keeping to be handled at compile time.
The following code prints sizeof(Foo) = 12 sizeof(FooS) = 4 with g++ 4.2 or 4.4 on an os/x 10.6 or Centos box.
Here Foo is boost::fusion::map<boost::fusion::pair<Name, int> >
Where are the extra 8 bytes going? With more complex boost::fusion objects I see an overhead of up to 16 bytes. gdb indicates that foo.data.vec has the desired size, but foo.data is larger, and foo is larger still; however, it doesn't indicate any data members --- is this some sort of alignment issue?
Is there a way to generate a "packed boost::fusion::map" without this space overhead?
Robert, I'm not familiar with fusion::map and don't have any idea how to make a "packed boost::fusion::map"; however, I think the container template specialization found here: http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_st... /container_all_of_aligned.hpp could be modified to provide what you want. The modification would simply replace the current "enum keys" with whatever key you might desire. Let me explain "enum keys". Currently, the container template in container_all_of_aligned.hpp is much like a boost::fusion::vector; however, the syntax for accessing the component values is a bit different. For fusion vector, the components are accessed with: at_c<KeyValue>(fusion_vector) [where KeyValue is some integral constant, say of type unsigned, between 0 and size(fusion_vector)-1] In contrast, a container_all_of_aligned accesses it's components with a templated member function: aligned_container.project<KeyValue>() where KeyValue is some integral type suitable as the 2nd argument to the boost::mpl::integral_c template. For example, the Index0 argument to the template: template < class Index0 , typename... Components
container < tags::all_of_aligned , Index0 , Components...
located here: https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates/boost/co... is actually an instance of boost::mpl_integral_c<KeyType,KeyValue> where the KeyValue corresonds to the 0-th component. KeyType could be unsigned (corresponding to the KeyType for fusion::vector) or, to be more user friendly, an enum type, e.g. enum component_indices { index_0 , index_1 ... , index_n }; Now, the method used by: aligned_container.project<KeyValue>() to access the component is just to call the overloaded project method: static TailComponent const& project ( index_part index_arg , char const* buffer_composite ) { void const* tail_buffer=buffer_composite+comp_part::offset; TailComponent const* tail_ptr=static_cast<TailComponentconst*>(tail_buffer); return *tail_ptr; } located here: https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates/boost/co... where index_part might be boost::mpl::integral_c<component_indices,index_0>. The actual component values are stored at offsets in the 2nd arg, buffer_composite, to the project static function. That offset, comp_part::offset, is a compile-time function of index_part. Now, intead of: boost::mpl::integral_c<KeyType,KeyValue> any type could used. The only important thing is that, because it's passed by value to project, it should be easy to copy or just empty, which boost::mpl::integral_c<KeyType,KeyValue> is. However, any other type can easily be adapted to this purpose by simply wrapping it in some templated empty type, such as that in boost/mpl/aux_/type_wrapper.hpp. Thus, instead of: typedef boost::mpl::integral_c<KeyType,KeyValue> index_part; for some KeyType, and KeyValue which is a KeyType, an index_part could be: typedef boost::mpl::aux::type_wrapper<KeyClassType> index_part; for some KeyClassType which would be the first element of one of the fusion::pair<KeyClassType,ValueType>'s making up the map. Actually, since no value is used, instead of fusion::pair, an mpl::pair could be used. Thus, since KeyClassType would not occur in any data structure, but only as a template argument to a function, it could cause no memory use (except maybe in the call stack, I guess). IOW, the algorithm used to calculate the size of buffer_composite does not depend in any way on the KeyClassType. Of course with this change, the layout_composite<,,C...>::scanned: https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates/boost/co... would have to be changed to take mpl::pair's instead of just components as the pack argument, C... . Robert, if you're interested in this approach, I'll start adding something similar to fusion::map to composite_storage. If not, then I'll just wait a while before doing that (I've been planning on doing it anyway). -regards, Larry