使用boost/program_options遇到的一点小问题 1.boost/program_options::options_description类 使用例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 po::options_description desc ("Allowed options" ) ; desc.add_options () ("help" , "produce help message" ) ("compression" , po::value <int >(), "set compression level" ) ; po::variables_map vm; po::store (po::parse_command_line (ac, av, desc), vm); po::notify(vm); if (vm.count ("help" )) { cout << desc << "\n" ; return 1 ; }if (vm.count ("compression" )) { cout << "Compression level was set to " << vm["compression" ].as <int >() << ".\n" ; } else { cout << "Compression level was not set.\n" ; }
这个po::add_options方法第一眼看有点奇怪,正好也遇到了Line 164 ,于是看了看解释和实现
手册解释: The add_options method of that class returns a special proxy object that defines operator(). Calls to that operator actually declare options,这个类的add_options方法返回了一个特殊的代理对象,这个对象重载了operator()
查看options_description类定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class options_description {public : options_description (unsigned = m_default_line_length, unsigned = m_default_line_length/2 ); options_description (const std::string &, unsigned = m_default_line_length, unsigned = m_default_line_length/2 ); void add (shared_ptr< option_description >) ; options_description & add (const options_description &) ; unsigned get_option_column_width () const ; options_description_easy_init add_options () ; const option_description & find (const std::string &, bool , bool = false , bool = false ) const ; const option_description * find_nothrow (const std::string &, bool , bool = false , bool = false ) const ; const std::vector< shared_ptr< option_description > > & options () const ; void print (std::ostream &, unsigned = 0 ) const ; friend BOOST_PROGRAM_OPTIONS_DECL std::ostream & operator <<(std::ostream &, const options_description &); static const unsigned m_default_line_length; };
看到返回的代理类是options_deescription_easy_init,于是看看其实现:
1 2 3 4 5 options_description_easy_init options_description::add_options () { return options_dscription_easy_init (this ); }
在来看看这个类的定义 ,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class options_description_easy_init {public : options_description_easy_init (options_description *); options_description_easy_init & operator () (const char *, const char *) ; options_description_easy_init & operator () (const char *, const value_semantic *) ; options_description_easy_init & operator () (const char *, const value_semantic *, const char *) ; };
果然重载了operator(),并且支持3种插入配置参数的规则: The parameters are option name, information about value, and option description.
然后到boost源码里面看看具体的实现boost/libs/program_options/src/options_description.cpp
摘出了一段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 options_description_easy_init& options_description_easy_init::operator ()(const char * name, const char * description) { shared_ptr<option_description> d ( new option_description(name, new untyped_value(true ), description)) ; owner->add (d); return *this ; } options_description_easy_init& options_description_easy_init::operator ()(const char * name, const value_semantic* s) { shared_ptr<option_description> d (new option_description(name, s)) ; owner->add (d); return *this ; } options_description_easy_init& options_description_easy_init::operator ()(const char * name, const value_semantic* s, const char * description) { shared_ptr<option_description> d (new option_description(name, s, description)) ; owner->add (d); return *this ; }
owner是指向被代理类的指针options_description *owner;
这个代理类构造一条option_description利用owner指针调用options_description::add()添加一条配置记录.
2. 小结
这应该是一个设计模式,但是我还不知道叫什么….
自己实现一下其中关系:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 c++#include <iostream> #include <map> #include <string> class Base ;class Base_init { private : Base *m_owner; public : Base_init (Base *owner):m_owner (owner) {} ~Base_init () {} public : Base_init &operator () (const char *a,const char *b) ; };class Base { private : std::map<std::string,std::string> _map; public : Base () {} ~Base () {} public : Base_init add_desc () ; void add (const char *a,const char *b) ; void print () ; };Base_init Base::add_desc () { return Base_init (this ); }void Base::add (const char *a,const char *b) { _map.insert (std::make_pair <std::string,std::string>(a,b)); }void Base::print () { std::map<std::string,std::string>::iterator it = _map.begin (); while (it != _map.end ()) { std::cout << it->first << " " << it->second << std::endl; it++; } }Base_init& Base_init::operator () (const char *a,const char *b) { m_owner->add (a,b); return *this ; }int main () { Base b; b.add_desc () ("key1" ,"llc1" ) ("key2" ,"llc2" ) ("key3" ,"llc3" ) ("key4" ,"llc4" ); b.print (); return 0 ; }