2013/2/21 Larry Evans :
I haven't a clear idea how this would work because I assumed that
the binary input stream would have to have something that
1st would be decoded into the tag for the variant.
Then, if your variant visitor solution is used, some
code (not shown) would create some default constructed value for
the bounded type corresponding to that tag and then call the visitor.
All the above is just off the top of my head, but, as I said,
I'm not real sure the variant visitor solution would work.
Could you provide more pseudo code to clarify.
Here is some more pseudo code, may be it will help you.
#include
struct name_visitor: public boost::static_visitorstd::string {
template <class T>
const std::string& opertor()(const T& val) const {
return val.name;
}
// Specific visitor for Person
std::string opertor()(const Person& val) const {
return val.first_name + " " + val.second_name;
}
// Specific visitor for Something
std::string opertor()(const Something& val) const {
throw std::logic_error("Class Something has no name!");
}
};
class EmployeePacket
{
typedef boost::variant variant_t;
std::vector Items;
EmployeePacket()
{
// copying variants is not as fast as copying pointers,
// so it is better to reserve some space first
Items.reserve(200);
}
void Decode(istream& Stream)
{
while (Stream) {
switch (Stream.getc()) {
case 'S': Items.push_back(String(Stream)); break;
case 'D': Items.push_back(Double(Stream)); break;
case 'P': Items.push_back(Person(Stream)); break;
}
}
}
double GetSalary(std::size_t index) const
{
// Will throw if at 'index' is not a Double type
return boost::get<Double>(Items[index]).value;
}
std::string GetName(std::size_t index) const {
return boost::apply_visitor(name_visitor(), Items[index]);
}
}
// All the folloving classes must have a constructor that accepts an istream&
class Double
{
string name;
string units;
// double decode_conversion_scale;
// double decode_conversion_translate;
// unsigned number_of_bits_used_to_encode
// double scale_factor
double value;
void Decode(istream& Stream) // Will be called from constructor
{
Stream.read(&value, 8);
value = value * decode_conversion_scale + decode_conversion_translate;
}
class String
{
string name;
string value;
void Decode(istream& Stream); // Will be called from constructor
}
class Person
{
string first_name;
string second_name;
void Decode(istream& Stream); // Will be called from constructor
}
class Something
{
/*string name; Has NO name! */
void Decode(istream& Stream);
}
Forgot to mention about disadvantages:
* slower copy construction and copy assignment of variant types
(compared to pointers)
* all the types used in variant must be full (not just forward declared)
If second disadvantage is 'too disadvantageous' for you, I can provide
exactly the same example with boost::any instead of boost::variant
--
Best regards,
Antony Polukhin