I have a question about the use of Any, especially when used in a larger facility such as program_options. There doesn't seem to be a (easy) way to post-process the results of a facility that has generically stuffed a bunch of values into a list of Any's. For example, if I wanted to a program to spit out all of its options to standard out, there doesn't seem to be any hooks to extract an Any value in a generic way (e.g., as a string). Granted, I could derive a class and add methods to do so, but that doesn't work when Any is already embedded in the program_options implementation. I certainly could be missing something here. I haven't used Any or program_options yet, and trying to understand all of the possibilities from the spec-like doc is hard. How do the rest of you do such things? -- Jeffery Cavallaro, 1055 Joaquin-191A Infrastructure Engineering Google Inc. 1600 Amphitheatre Parkway Mountain View, CA 94043 650-214-2552
Jeffery Cavallaro <jcavalla <at> google.com> writes: [...]
For example, if I wanted to a program to spit out all of its options to standard out, there doesn't seem to be any hooks to extract an Any value in a generic way (e.g., as a string).
Okay, this isn't exactly generic and only addresses this specific case for the issue that you brought up, but for program_options where you normally just have a limited number of types I've used: ... for ( po::variables_map::const_iterator cur = _options.begin() , end = _options.end() ; cur != end ; ++cur) { #define CLI_print_for_type(Type) \ else if (cur->second.value().type() == typeid(Type)) { \ LogKeyValuePair( logger, option_entry_format \ , cur->first \ , boost::any_cast<Type>(cur->second.value())); \ } // end macro definition if (cur->second.value().type() == typeid(void)) { logger.Write(str(option_entry_format % cur->first % "<empty>")); } CLI_print_for_type(int) CLI_print_for_type(bool) CLI_print_for_type(std::string) else { logger.Write(str(option_entry_format % cur->first % "<unknown>")); } #undef CLI_print_for_type } ... -Ryan
On Wed, Apr 23, 2008 at 05:06:58AM +0000, Ryan Gallagher wrote:
Jeffery Cavallaro <jcavalla <at> google.com> writes: [...]
For example, if I wanted to a program to spit out all of its options to standard out, there doesn't seem to be any hooks to extract an Any value in a generic way (e.g., as a string).
Okay, this isn't exactly generic and only addresses this specific case for the issue that you brought up, but for program_options where you normally just have a limited number of types I've used:
I've done something similar as well. If you have a lot of types, and you want support for vectors of those types, you may want to look at the boost preprocessor macro library: ... #define TYPE_LIST ( unsigned char, ( unsigned short, ( unsigned int, ( unsigned long, ( signed char, ( signed short, ( signed int, ( signed long, ( bool, ( char, ( std::string, BOOST_PP_NIL))))))))))) #define MAKE_VECTOR_LIST( d, data, elem ) std::vector<elem> #define VECTOR_LIST BOOST_PP_LIST_TRANSFORM( MAKE_VECTOR_LIST, _, TYPE_LIST ) #define CAST_SIMPLE( r, data, elem ) if ( ti == typeid( elem ) ) { elem e = anyValue->as<elem>(); return boost::lexical_cast<string>( e ); } #define CAST_VECTOR( r, data, elem ) if ( ti == typeid( elem ) ) { /* iterate through the vector... */ } BOOST_PP_LIST_FOR_EACH(CAST_SIMPLE, _, TYPE_LIST); BOOST_PP_LIST_FOR_EACH(CAST_VECTOR, _, VECTOR_LIST); ... Andrew.
On Wed, Apr 23, 2008 at 05:06:58AM +0000, Ryan Gallagher wrote:
Jeffery Cavallaro <jcavalla <at> google.com> writes: [...]
For example, if I wanted to a program to spit out all of its options to standard out, there doesn't seem to be any hooks to extract an Any value in a generic way (e.g., as a string).
Okay, this isn't exactly generic and only addresses this specific case for the issue that you brought up, but for program_options where you normally just have a limited number of types I've used:
I've done something similar as well. If you have a lot of types, and you want support for vectors of those types, you may want to look at the boost preprocessor macro library:
So, could somebody write a visit_any function / macro, or do we need to do some kind of hack each time. I am imagining a visit_any function that takes an mpl vector of types as an argument ... -- John Femiani
On 24/04/2008, John Femiani <JOHN.FEMIANI@asu.edu> wrote:
On Wed, Apr 23, 2008 at 05:06:58AM +0000, Ryan Gallagher wrote:
Jeffery Cavallaro <jcavalla <at> google.com> writes: [...]
For example, if I wanted to a program to spit out all of its options to standard out, there doesn't seem to be any hooks to extract an Any value in a generic way (e.g., as a string).
Okay, this isn't exactly generic and only addresses this specific case for the issue that you brought up, but for program_options where you normally just have a limited number of types I've used:
I've done something similar as well. If you have a lot of types, and you want support for vectors of those types, you may want to look at the boost preprocessor macro library:
So, could somebody write a visit_any function / macro, or do we need to do some kind of hack each time. I am imagining a visit_any function that takes an mpl vector of types as an argument ...
This has been discussed many times in the dev list I think, search for 'any visitor' in the archives. I posted a small utility some time ago as a base for discussion. It was named badly (any_variant), since I needed a visitor mechanism identical to the one in boost::variant , maybe it could be of some use to someone =) http://lists.boost.org/Archives/boost/2007/09/127126.php / Christian
-- John Femiani
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Hello, I've got a class template that one of its members is boost::variant: template<?> class MyClass { boost::variant</*bounded types*/> var_; }; At the stage of MyClass instantiation, I'd like to specify variant' bounded types list - which is variable. What's the most simple way to do this? Can I use mpl::list somehow - both as MyClass template parameter and in the variant specialization? Thank you. _________________________________________________________________ Explore the seven wonders of the world http://search.msn.com/results.aspx?q=7+wonders+world&mkt=en-US&form=QBRE
Jeffery Cavallaro schrieb:
For example, if I wanted to a program to spit out all of its options to standard out, there doesn't seem to be any hooks to extract an Any value in a generic way (e.g., as a string). Granted, I could derive a class and add methods to do so, but that doesn't work when Any is already embedded in the program_options implementation.
I made a wrapper class for boost::any (output_any) that allows to output any type that is output streamable. This method is my poor man's serialization method to convert a bunch of objects to a text representation. A full code example is below. Wouldn't it make sense to have something like output_any as a companion to boost::any in the boost distribution? Regards James BTW: If runtime performance is more important then memory, the calls to outputter_factory::get_outputter<T>() can be replaced by "new outputter<T>" #include <string> #include <iostream> #include <vector> #include <map> #include <boost/any.hpp> #include <boost/shared_ptr.hpp> #include <boost/date_time/posix_time/posix_time.hpp> using namespace boost; using namespace boost::posix_time; using namespace std; /** Interface for outputting "any" */ struct base_out { typedef shared_ptr<base_out> ptr; virtual void output(ostream &o, const any &a) const = 0; }; /** Concrete outputter for "any" of type T */ template<typename T> struct outputter : public base_out { void output(ostream &o, const any &a) const { const T& c = any_cast<T>(a); o << c; } }; /** Creates outputter instances for different types. */ class outputter_factory { public: /** Returns an outputter for type T - not threadsafe! * @throws bad_allow if the new outputter * cannot be inserted into the map. */ template<typename T> static base_out::ptr get_outputter() { const char * type_name = typeid(T).name(); ptr_map::const_iterator f = ptrs_.find(type_name); if (f == ptrs_.end()) { pair<ptr_map::iterator, bool> ret = ptrs_.insert(make_pair(type_name, base_out::ptr(new outputter<T>))); if (!ret.second) { throw bad_alloc("Could not insert new outputter into map"); } f = ret.first; } return f->second; } private: typedef map<const char*, base_out::ptr> ptr_map; static ptr_map ptrs_; }; outputter_factory::ptr_map outputter_factory::ptrs_; /** Allows to output just "any"thing. Inspired by the class any_out * in the book "Beyond the C++ Standard Library" */ class output_any { public: /** Default c'tor */ output_any() {} /** Construction from any object of type T */ template<typename T> output_any(const T &a) : outputter_(outputter_factory::get_outputter<T>()), a_(a) {} /** Copy c'tor */ output_any(const output_any &other) : outputter_(other.outputter_), a_(other.a_) {} /** Assignment from other output_any */ output_any& operator=(output_any& r) { outputter_ = r.outputter_; a_ = r.a_; return *this; } /** Assignment from any instance of type T */ template<typename T> output_any& operator=(const T& t) { outputter_ = outputter_factory::get_outputter<T>(); a_ = any(t); return *this; } /** Safely swaps *this with other */ output_any &swap(output_any &other) { a_.swap(other.a_); outputter_.swap(other.outputter_); return *this; } /** Give the ostream operator acces to * our private methods and vars. */ friend ostream & operator<<(ostream &o, const output_any &a); private: /** Outputs a_ */ void output(ostream &o) const { if (outputter_) { outputter_->output(o, a_); } } base_out::ptr outputter_; any a_; }; /** Output an output_any */ ostream & operator<<(ostream &o, const output_any &a) { a.output(o); return o; } /** Prints all elements of the container c line by line * to cout */ template<typename Container> void output_all(const Container &c) { for(Container::const_iterator i = c.begin(); i != c.end(); ++i) { cout << *i << endl; } } /** Some dummy class to show that ouput_any can * output - well - any type that defines and output * operator. */ class my_type { public: my_type(int a, int b) : a_(a), b_(b) {} friend ostream & operator<<(ostream &o, const my_type &m); private: int a_, b_; }; /** Output my_type */ ostream & operator<<(ostream &o, const my_type &m) { o << "a is " << m.a_ << " and b is " << m.b_; return o; } int main() { output_any o1(10); output_any o2(3.1415); output_any o3(string("foo")); output_any o4; o4 = o3; o4 = string("gugus"); output_any o5; o5 = my_type(33, 44); o1.swap(o3); cout << o1 << endl; cout << o2 << endl; cout << o3 << endl; cout << o4 << endl; cout << o5 << endl; // Put some output_any instance into a vector // and output all of them... vector<output_any> some_values; some_values.push_back(output_any(string("bar"))); some_values.push_back(output_any(1500)); some_values.push_back(output_any(34)); some_values.push_back(output_any(193)); some_values.push_back(output_any(1.2345)); some_values.push_back(output_any(my_type(10, 30))); some_values.push_back(output_any(second_clock::local_time())); cout << endl << "The values from the container:" << endl; output_all(some_values); string in; getline(cin, in); return 0; }
participants (7)
-
Andrew Agno
-
Christian Holmquist
-
Igor R.
-
Jean-Pierre Bergamin
-
Jeffery Cavallaro
-
John Femiani
-
Ryan Gallagher