[gsoc][review/comments] Request community input on project interface

Hello, I'm currently working on my GSoC project and I wanted some feedback from the community about the interface of a data structure I'm working on called a "bitfield_tuple". The bitfield_tuple makes it easy and simple to create and use specific bitfields. Currently, this works only over integral types, although there are plans to extend this in later versions of the data structure. bitfield_tuples correctly work with different types of endianness as well as provide the mechanisms to allow users to explicitly define the size of the structure's storage space. The bitfield_tuple is a tuple like sequence of elements but, instead of providing direct access to an instance of a type, a proxy to the element stored within the bitfield_tuple is returned. This is similar to std::vector<bool>'s reference type. Example bitfield_tuple declaration, struct red; struct green; struct blue; typedef bitfield_tuple< storage<unsigned int>, member<int,red,5>, member<int,green,6>, member<ing,blue,5>
bft_example;
The internal storage type which all of the bitfields are stored in is specified by the storage template. The members are used to specify the different bitfields which are to be stored within that storage type. The member template is specified the exact same way a normal c++ bitfield would be specified inside of a struct or class. int red:5; member<int,red,5> A member template is specified in the order of: type, name, width of bitfield. The order the member templates are given in is the order in which they are stored within the bitfield_tuple. However, the storage template does not take up an index within the bitfield_tuple. So the template member<int,red,5> will be stored at index 0. Each member template requires a name be specified; this is for ease of access, later described in the get function. Each name must be unique within a single bitfield_tuple. The width of the bitfield is handled internally. The starting point for each bitfield is the bit after the previous bitfield, or 0 if it's the first bitfield. bitfield_tuple interface summary: Default constructor, copy constructor, and a constructor which allows for the construction over an initial value which is of the same as the storage type. bitfield_tuple(); bitfield_tuple (bitfield_tuple const&); bitfield_tuple (storage_type); Assignment operators for assignment from the storage type, similar to the constructor above, and copy assignment. bitfield_tuple const& operator=(storage_type); bitfield_tuple const& operator=(bitfield_tuple const&); The get function operates similar to the boost.tuple with slight modification. Specifically, the get function will return a reference type. There are two ways to use the get function. The first way is by using a unsigned integral constant as an index: bft_example temp; temp.get<0>(); // returns a proxy reference to the bitfield represented by member<int,red,5> The second way to use it is to call get using the name provided to the member parameter: temp.get<red>(); // does the same thing as get<0>(); I provide both const and non const versions of both functions. The bitfield_tuple is also a boost.fusion sequence. It models an associative array type by using the following category: struct bft_category : boost::fusion::random_access_ traversal_tag, boost::fusion::associative_tag { }; The btifield_tuple's fusion extension was created through the fusion sequence extension provided by boost.fusion. bitfield_tuple supports the following fusion functions and all of the intrinsic functions which are supported from the implementation of these functions. begin end is_sequence is_view category_of at size at_key tag_of The btifield_tuple_iterator supports the following fusion functions: deref value_of next prior distance key_of value_at_data deref_data advance If you would like to look at the code for bitfield_tuple, it is located here: http://svn.boost.org/svn/boost/sandbox/SOC/2010/bit_masks/boost/integer/bitf... -- thanks, Brian Bartman

At Mon, 21 Jun 2010 12:39:40 -0400, Brian Bartman wrote:
Hello,
I'm currently working on my GSoC project and I wanted some feedback from the community about the interface of a data structure I'm working on called a "bitfield_tuple". The bitfield_tuple makes it easy and simple to create and use specific bitfields.
Cool.
Currently, this works only over integral types, although there are plans to extend this in later versions of the data structure. bitfield_tuples correctly work with different types of endianness as well as provide the mechanisms to allow users to explicitly define the size of the structure's storage space.
I think you need to define what you consider to be “correctly working with different types of endianness.”
The bitfield_tuple is a tuple like sequence of elements but, instead of providing direct access to an instance of a type, a proxy to the element stored within the bitfield_tuple is returned. This is similar to std::vector<bool>'s reference type.
Example bitfield_tuple declaration,
struct red; struct green; struct blue;
typedef bitfield_tuple< storage<unsigned int>, member<int,red,5>, member<int,green,6>, member<ing,blue,5>
bft_example;
The internal storage type which all of the bitfields are stored in is specified by the storage template. The members are used to specify the different bitfields which are to be stored within that storage type. The member template is specified the exact same way a normal c++ bitfield would be specified inside of a struct or class.
int red:5;
Not valid C++ AFAIK.
member<int,red,5>
A member template is specified in the order of: type, name, width of bitfield.
So these “names” (struct tags) are a way of referring to different fields? Is it possible to refer to them by index?
The order the member templates are given in is the order in which they are stored within the bitfield_tuple. However, the storage template does not take up an index within the bitfield_tuple. So the template member<int,red,5> will be stored at index 0. Each member template requires a name be specified; this is for ease of access, later described in the get function. Each name must be unique within a single bitfield_tuple. The width of the bitfield is handled internally. The starting point for each bitfield is the bit after the previous bitfield, or 0 if it's the first bitfield.
I think you need to define “after.”
bitfield_tuple interface summary:
Default constructor, copy constructor, and a constructor which allows for the construction over an initial value which is of the same as the storage type.
bitfield_tuple(); bitfield_tuple (bitfield_tuple const&); bitfield_tuple (storage_type);
That last one should be explicit because of the possibility of narrowing.
Assignment operators for assignment from the storage type, similar to the constructor above, and copy assignment.
bitfield_tuple const& operator=(storage_type); bitfield_tuple const& operator=(bitfield_tuple const&);
The get function operates similar to the boost.tuple with slight modification. Specifically, the get function will return a reference type.
?? boost.tuple's get<> doesn't return a reference? How can you return a reference to three bits? Didn't you already tell us you were using proxies?
There are two ways to use the get function. The first way is by using a unsigned integral constant as an index:
bft_example temp; temp.get<0>(); // returns a proxy reference to the bitfield represented by member<int,red,5>
The second way to use it is to call get using the name provided to the member parameter:
temp.get<red>(); // does the same thing as get<0>();
I provide both const and non const versions of both functions.
The bitfield_tuple is also a boost.fusion sequence. It models an associative array type by using the following category:
struct bft_category : boost::fusion::random_access_
traversal_tag, boost::fusion::associative_tag { };
Good! I hope you find these comments helpful. Regards, -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Currently, this works only over integral types, although there are plans to extend this in later versions of the data structure. bitfield_tuples correctly work with different types of endianness as well as provide the mechanisms to allow users to explicitly define the size of the structure's storage space.
I think you need to define what you consider to be “correctly working with different types of endianness.”
OK I'll do my best to better describe the internal workings of the type with regards to the endianness of the storage type, with in my documentation.
The bitfield_tuple is a tuple like sequence of elements but, instead of providing direct access to an instance of a type, a proxy to the element stored within the bitfield_tuple is returned. This is similar to std::vector<bool>'s reference type.
Example bitfield_tuple declaration,
struct red; struct green; struct blue;
typedef bitfield_tuple< storage<unsigned int>, member<int,red,5>, member<int,green,6>, member<ing,blue,5>
bft_example;
The internal storage type which all of the bitfields are stored in is specified by the storage template. The members are used to specify the different bitfields which are to be stored within that storage type. The member template is specified the exact same way a normal c++ bitfield would be specified inside of a struct or class.
int red:5;
Not valid C++ AFAIK.
Sorry I should clarify that. struct a { ... int red:5; ... };
member<int,red,5>
A member template is specified in the order of: type, name, width of bitfield.
So these “names” (struct tags) are a way of referring to different fields? Is it possible to refer to them by index?
You can use index or name which ever you prefer.
The order the member templates are given in is the order in which they are stored within the bitfield_tuple. However, the storage template does not take up an index within the bitfield_tuple. So the template member<int,red,5> will be stored at index 0. Each member template requires a name be specified; this is for ease of access, later described in the get function. Each name must be unique within a single bitfield_tuple. The width of the bitfield is handled internally. The starting point for each bitfield is the bit after the previous bitfield, or 0 if it's the first bitfield.
I think you need to define “after.”
I can do that and I'll be sure to note just how it works in my documentation.
bitfield_tuple interface summary:
Default constructor, copy constructor, and a constructor which allows for the construction over an initial value which is of the same as the storage type.
bitfield_tuple(); bitfield_tuple (bitfield_tuple const&); bitfield_tuple (storage_type);
That last one should be explicit because of the possibility of narrowing.
OK thanks. I'll do that.
Assignment operators for assignment from the storage type, similar to the constructor above, and copy assignment.
bitfield_tuple const& operator=(storage_type); bitfield_tuple const& operator=(bitfield_tuple const&);
The get function operates similar to the boost.tuple with slight modification. Specifically, the get function will return a reference type.
?? boost.tuple's get<> doesn't return a reference? How can you return a reference to three bits? Didn't you already tell us you were using proxies?
Sorry. It seems I was unclear again. its a proxy reference tpye that acts as a front end to the internal bits.
I hope you find these comments helpful.
Thanks for the fast reply, the information was extremely useful.
Regards,
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- thanks, Brian Bartman

At Mon, 21 Jun 2010 13:02:29 -0400, Brian Bartman wrote:
Currently, this works only over integral types, although there are plans to extend this in later versions of the data structure. bitfield_tuples correctly work with different types of endianness as well as provide the mechanisms to allow users to explicitly define the size of the structure's storage space.
I think you need to define what you consider to be “correctly working with different types of endianness.”
OK I'll do my best to better describe the internal workings of the type with regards to the endianness of the storage type, with in my documentation.
I don't think internal workings is what I'm interested in. I *would* like to know what kind of storage layout in memory I get on both big- and little- endian machines, though. If you could give rationale about why those design choices are the “correct” ones too, it would be a bonus.
Assignment operators for assignment from the storage type, similar to the constructor above, and copy assignment.
bitfield_tuple const& operator=(storage_type); bitfield_tuple const& operator=(bitfield_tuple const&);
The get function operates similar to the boost.tuple with slight modification. Specifically, the get function will return a reference type.
?? boost.tuple's get<> doesn't return a reference? How can you return a reference to three bits? Didn't you already tell us you were using proxies?
Sorry. It seems I was unclear again. its a proxy reference tpye that acts as a front end to the internal bits.
If you had said “Specifically, bitfield_tuple's get function returns a proxy reference” it would have been crystal clear. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Mon, Jun 21, 2010 at 1:18 PM, David Abrahams <dave@boostpro.com> wrote:
At Mon, 21 Jun 2010 13:02:29 -0400, Brian Bartman wrote:
Currently, this works only over integral types, although there are plans to extend this in later versions of the data structure. bitfield_tuples correctly work with different types of endianness as well as provide the mechanisms to allow users to
explicitly
define the size of the structure's storage space.
I think you need to define what you consider to be “correctly working with different types of endianness.”
OK I'll do my best to better describe the internal workings of the type with regards to the endianness of the storage type, with in my documentation.
I don't think internal workings is what I'm interested in. I *would* like to know what kind of storage layout in memory I get on both big- and little- endian machines, though. If you could give rationale about why those design choices are the “correct” ones too, it would be a bonus.
The internal memory access and modification is managed by bitfield (which is currently in the boost vault) and was written by my mentor Vicente Botet. I'll have to get back to you after I know more about how his data structure handles endianness.
Assignment operators for assignment from the storage type, similar to the constructor above, and copy assignment.
bitfield_tuple const& operator=(storage_type); bitfield_tuple const& operator=(bitfield_tuple const&);
The get function operates similar to the boost.tuple with slight modification. Specifically, the get function will return a reference type.
?? boost.tuple's get<> doesn't return a reference? How can you return a reference to three bits? Didn't you already tell us you were using proxies?
Sorry. It seems I was unclear again. its a proxy reference tpye that acts as a front end to the internal bits.
If you had said “Specifically, bitfield_tuple's get function returns a proxy reference” it would have been crystal clear.
Oh. OK.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- thanks, Brian Bartman

Brian Bartman wrote:
On Mon, Jun 21, 2010 at 1:18 PM, David Abrahams <dave@boostpro.com> wrote:
At Mon, 21 Jun 2010 13:02:29 -0400, Brian Bartman wrote:
Currently, this works only over integral types, although there are plans to extend this in later versions of the
data
structure. bitfield_tuples correctly work with different types of endianness as well as provide the mechanisms to allow users to explicitly define the size of the structure's storage space.
I think you need to define what you consider to be “correctly working with different types of endianness.”
OK I'll do my best to better describe the internal workings of the type with regards to the endianness of the storage type, with in my documentation.
I don't think internal workings is what I'm interested in. I *would* like to know what kind of storage layout in memory I get on both big- and little- endian machines, though. If you could give rationale about why those design choices are the “correct” ones too, it would be a bonus.
The internal memory access and modification is managed by bitfield (which is currently in the boost vault) and was written by my mentor Vicente Botet. I'll have to get back to you after I know more about how his data structure handles endianness.
The bitfield class expect an INTEGER-LIKE storage type. Usually the storage type will be a native type. In this case, the conversion to/from a specific endian type, can be made at once for all the bitfields of the same storage, as it was an other integer type, i.e. at the I/O level. We can use also an endian aware integer type as storage, such as boost::integer::endian<> as defined in Boost.Endian. In this case each bitfield read access results in a conversion from the endian storage to the native type plus the mask operation itself and each bitfield write access results in conversion from the endian storage to the native type, the mask operation itself plus conversion from the native storage to the endian type. These conversions are done transparently through the INTEGER-LIKE conversion operator and assignment. Best, Vicente -- View this message in context: http://old.nabble.com/-gsoc--review-comments--Request-community-input-on-pro... Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (3)
-
Brian Bartman
-
David Abrahams
-
Vicente Botet Escriba