使用boost/program_options遇到的一点小问题

使用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,于是看了看解释和实现

  1. 手册解释: 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()

  2. 查看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
    // In header: <boost/program_options/options_description.hpp>


    class options_description {
    public:
    // construct/copy/destruct
    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);

    // public member functions
    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 functions
    friend BOOST_PROGRAM_OPTIONS_DECL std::ostream &
    operator<<(std::ostream &, const options_description &);

    // public data members
    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
   // In header: <boost/program_options/options_description.hpp>


class options_description_easy_init {
public:
// construct/copy/destruct
options_description_easy_init(options_description *);
// public member functions
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

摘出了一段:

   options_description_easy_init&
   options_description_easy_init::
   operator()(const char* name,
              const char* description)
   {
       // Create untypes semantic which accepts zero tokens: i.e. 
       // no value can be specified on command line.
       // FIXME: does not look exception-safe
       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);
/*
Base_init &operator()(const char *a,const value_semantic *s) {}
Base_init &operator()(const char *a,const value_semantic *s,const char *description) {}
*/
};

//被代理的类
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;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!