[boost-users][Variant] Sequence instantiation
I have a sequence of types defined with the Loki library. I believe the
equivalent would be boost::mpl::vector. The sequence is used to cause
compile time asserts for unsupported types being passed to template
functions. Boost variant can be created with a given list of types.
typedef boost::variant< int, std::string, short, long > type_list;
|
AMDG Ryan McConnehey wrote:
I have a sequence of types defined with the Loki library. I believe the equivalent would be boost::mpl::vector. The sequence is used to cause compile time asserts for unsupported types being passed to template functions. Boost variant can be created with a given list of types.
typedef boost::variant< int, std::string, short, long > type_list; |
| Is it possible to create a variant from a sequence by either passing the sequence or iterating through each value in the sequence? This would reduce the code duplication of having one sequence for assert checking and the other for variants.
Use the metafunction boost::make_variant_over. In Christ, Steven Watanabe
On Tue, Aug 25, 2009 at 10:12 PM, Steven Watanabe
AMDG
Ryan McConnehey wrote:
I have a sequence of types defined with the Loki library. I believe the equivalent would be boost::mpl::vector. The sequence is used to cause compile time asserts for unsupported types being passed to template functions. Boost variant can be created with a given list of types.
typedef boost::variant< int, std::string, short, long > type_list; |
| Is it possible to create a variant from a sequence by either passing the sequence or iterating through each value in the sequence? This would reduce the code duplication of having one sequence for assert checking and the other for variants. Use the metafunction boost::make_variant_over.
I doubt Boost.Variant is the best choice for this. You say a template function to enforce types, I would say Boost.Enable_if combined with Boost.Type_traits and Boost.MPL would make it real easy.
I doubt Boost.Variant is the best choice for this. You say a template function to enforce types, I would say Boost.Enable_if combined with Boost.Type_traits and Boost.MPL would make it real easy.
I'm all for making this easy. So, let me give you some background of what I'm trying to do. I'm reading an xml file that contains a binary format description (lets call the class BFD). This will allow me to specify a customers binary data in such a way as to place the binary data into an object. Each parameter has a type associated with it. This can be a int, short, string, long etc. The class reading the xml file is storing the type information based on the parameter name. Any class trying to retrieve this binary format description will need to specify the parameter name and expected type. If the parameter name exists but the type is incorrect then an empty description is returned. I need to limit the types that can be requested from the BFD. That's where the mpl::vector of known types comes into play. The function returning the binary description information will check (at compile time) to make sure the type requested is part of the known types. Since the BFD is comparing types I need to convert the string names of these types, in the xml file, into real types. This has posed a problem. I come up with nothing better than a case statement. Once the type is known I then create a binary format description object (this is a template structure). The only reason the structure is a template is to associate a type. This is why I though the boost::variant was necessary. A variant composed of each of the types in the mpl::vector was defined as the second parameter of a map with the key as the parameter name from the xml file. The function returning the binary description information will check the type of the data stored in the map and if the types match then return the structure. So with this information in mind how would you use the boost::enable_if, boost::type_traits and boost:mpl. Ryan
On Wed, Aug 26, 2009 at 8:32 PM, Ryan McConnehey
I doubt Boost.Variant is the best choice for this. You say a template function to enforce types, I would say Boost.Enable_if combined with Boost.Type_traits and Boost.MPL would make it real easy.
I'm all for making this easy. So, let me give you some background of what I'm trying to do. I'm reading an xml file that contains a binary format description (lets call the class BFD). This will allow me to specify a customers binary data in such a way as to place the binary data into an object. Each parameter has a type associated with it. This can be a int, short, string, long etc. The class reading the xml file is storing the type information based on the parameter name. Any class trying to retrieve this binary format description will need to specify the parameter name and expected type. If the parameter name exists but the type is incorrect then an empty description is returned.
I need to limit the types that can be requested from the BFD. That's where the mpl::vector of known types comes into play. The function returning the binary description information will check (at compile time) to make sure the type requested is part of the known types. Since the BFD is comparing types I need to convert the string names of these types, in the xml file, into real types. This has posed a problem. I come up with nothing better than a case statement. Once the type is known I then create a binary format description object (this is a template structure). The only reason the structure is a template is to associate a type. This is why I though the boost::variant was necessary. A variant composed of each of the types in the mpl::vector was defined as the second parameter of a map with the key as the parameter name from the xml file. The function returning the binary description information will check the type of the data stored in the map and if the types match then return the structure.
So with this information in mind how would you use the boost::enable_if, boost::type_traits and boost:mpl.
Ah, I did not have enough information, in that case I would use Boost.Variant as the container with something like Spirit2.1's string table to do a faster type (string->type and parsing) lookup, that would give you excellent speed for that purpose. Something like Boost.Fusion's map would also work as well, but which is better depends on how much of the work is done at compile-time and how much is done at run-time, I am not fully clear about that, I do not suppose you could show some pseudo-code of what you want?
I do not suppose you could show some pseudo-code of what you want?
In the xml file a parameter has an element entry and is placed into the following structure. <field name="velocity_x" type="uint8_t" destination_byte="0"/> struct Desintation { unsigned char source_bit; unsigned long length; unsigned long destination_byte; unsigned char destinatoin_bit_of_byte; }; Upon parsing the xml file the string name of the type must be converted into the actual type. Then the size of the type must calculated and placed into the length variable. From this class the Destination structure needs to be passed back if the parameter name and type matches the recorded information in the xml file. A peudo function is as follows. template <typename T> std::vector<Destination> get(std::string name) { Assert if T isn't in the defined list of support types. Search the storage container for the parameter name and type. if parameter name and type match return the stored vector of Destination structures. else return an empty vector of Destination structures. } A vector of Destination structures is stored because a parameter name can have sub-elements that describe bit locations of data that are used to retrieve the overall parameter value. Let me know what you think. Ryan
On Thu, Aug 27, 2009 at 4:43 PM, Ryan McConnehey
I do not suppose you could show some pseudo-code of what you want?
In the xml file a parameter has an element entry and is placed into the following structure.
<field name="velocity_x" type="uint8_t" destination_byte="0"/>
struct Desintation { unsigned char source_bit; unsigned long length; unsigned long destination_byte; unsigned char destinatoin_bit_of_byte; };
Upon parsing the xml file the string name of the type must be converted into the actual type. Then the size of the type must calculated and placed into the length variable. From this class the Destination structure needs to be passed back if the parameter name and type matches the recorded information in the xml file. A peudo function is as follows.
template <typename T> std::vector<Destination> get(std::string name) { Assert if T isn't in the defined list of support types. Search the storage container for the parameter name and type. if parameter name and type match return the stored vector of Destination structures. else return an empty vector of Destination structures. }
A vector of Destination structures is stored because a parameter name can have sub-elements that describe bit locations of data that are used to retrieve the overall parameter value.
Let me know what you think.
Ah, for something like that I personally would use Variant to hold it all, Spirit2.1 (with stringtable > continued parsing trick, Spirit2.1 is in the boost trunk but it works on older boosts' too) to parse it, would give the best speed and is easily extensible in the future while being completely typesafe.
Ah, for something like that I personally would use Variant to hold it all, Spirit2.1 (with stringtable > continued parsing trick, Spirit2.1 is in the boost trunk but it works on older boosts' too) to parse it, would give the best speed and is easily extensible in the future while being completely typesafe.
I'm assuming the Spirit 2.1 is just for parsing the xml file. I still
need to have a switch statement to determine what type I'm suppose to be
storing. Lets suppose for a moment that I've determined the type to be
stored (whether Spirit 2.1, tinyXML or some other parser). I've tried
making the Destination class a template based on type (see code at
bottom of email). Then I created a variant of all the Destination class
with the types I wanted. A map was used with a key for the parameter
name and the value was a vector of the variants. Matching the parameter
name is simple in the get function. I've had trouble comparing the type
and then returning just a vector of that type and not a vector of the
variant. It seams that since the caller knows what type they want that
I shouldn't have to return a variant.
This approach seem to be complicating the return value. The only reason
to to make Destination a template was to keep track of the type. Is
there a way to keep track of the type in the key or something? That way
the Destination class can be simple and keep the return simple. The
caller knows what type they want and if it isn't there the return vector
will be empty. Can you provide some code on what you might suggest?
Ryan
Code:
typedef boost::mpl::vector< Destination<long>, Destination<short>,
Destinationstd::string > supported_types;
typedef
boost::variant::make_variant_over
supported_list;
On Thu, Aug 27, 2009 at 9:13 PM, Ryan McConnehey
Ah, for something like that I personally would use Variant to hold it all, Spirit2.1 (with stringtable > continued parsing trick, Spirit2.1 is in the boost trunk but it works on older boosts' too) to parse it, would give the best speed and is easily extensible in the future while being completely typesafe.
I'm assuming the Spirit 2.1 is just for parsing the xml file. I still need to have a switch statement to determine what type I'm suppose to be storing.
You can use it for parsing the XML file, but I am not even talking
about that. Spirit has a little ternary tree designed for fast
lookups, you could lookup the type in that, it will return a parser,
then you can run the string that inits that type through that parser
to create the type. You could of course put it in a larger parser to
parse the whole xml file, but for just that purpose alone it would
still rule for this purpose.
On Thu, Aug 27, 2009 at 9:13 PM, Ryan McConnehey
Lets suppose for a moment that I've determined the type to be stored (whether Spirit 2.1, tinyXML or some other parser). I've tried making the Destination class a template based on type (see code at bottom of email). Then I created a variant of all the Destination class with the types I wanted. A map was used with a key for the parameter name and the value was a vector of the variants. Matching the parameter name is simple in the get function. I've had trouble comparing the type and then returning just a vector of that type and not a vector of the variant. It seams that since the caller knows what type they want that I shouldn't have to return a variant.
This approach seem to be complicating the return value. The only reason to to make Destination a template was to keep track of the type. Is there a way to keep track of the type in the key or something? That way the Destination class can be simple and keep the return simple. The caller knows what type they want and if it isn't there the return vector will be empty. Can you provide some code on what you might suggest?
Since you are parsing something at runtime to figure out types, you
cannot really know what to return at compile time, hence the use of
the variant. I'd might make something like this (pseudo-code):
struct someStruct {int i; float f;};
MAKE_FUSION_VECTOR_OVER_STRUCT(someStruct,(int,i)(float,f)); // or
whatever the name of the macro was...
typedef variant
Ryan
Code: typedef boost::mpl::vector< Destination<long>, Destination<short>, Destinationstd::string > supported_types; typedef boost::variant::make_variant_over
::type supported_variant; std::map< std::string, std::vector > supported_list; _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks for the code example. I'm currently trying to work through it and integrate it with my code. Ryan
participants (3)
-
OvermindDL1
-
Ryan McConnehey
-
Steven Watanabe