boost::program_options学习总结

boost::program_options学习总结

  • 简介
  • 编程实践
    • 小试牛刀
    • 多选项细化设计
    • 多源文件设计
    • CMakeLists文件
  • 参考链接:

简介

Boost C++ 库(Libraries)是一组扩展C++功能的经过同行评审(Peer-reviewed)且开放源码程序库。大多数的函数为了能够以开放源码、封闭项目的方式运作,而许可于Boost软件许可协议(Boost Software License)之下。许多Boost的开发人员是来自C++标准委员会,而部分的Boost库成为C++的TR1标准之一。

boost::program_options提供了一种很方便的命令行接口,可以简化人机交互的流程。使用该库文件中提供的方法,可以方便的通过交互界面对工程进行参数设置和运行配置。

编程实践

在ubuntu环境下进行编程实验。练习了三个编程实验,分别如下:

小试牛刀

第一个示例是最简单的示例:它仅处理两个选项。

boost_test.cpp

#include 
#include 
#include 

using namespace std;
namespace po = boost::program_options;

int main(int argc, char ** argv)
{
    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(argc, argv, 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,方便后面使用。通过options_description类声明了需要的选项,add_options返回了定义了operator()的特殊的代理对象。对该运算符的调用实际上声明了选项。 参数是选项名称,有关值的信息和选项描述。 在此示例中,第一个选项没有值,第二个选项具有int类型的值。

接下来,声明了variables_map类的对象,它主要用来存储选项值,并且能储存任意类型的值。然后,store,parse_command_line和notify函数使vm能存储在命令行中发现的选项。

最后,我们可以根据需要使用这些选项。 除了必须使用上面显示的as方法检索存储在其中的值之外,可以像std :: map一样使用variables_map类。 (如果对as方法的调用中指定的类型与实际存储的类型不同,则将引发异常。)

运行结果:

bruce@bruce-K45VD:~/study/boost_study/build$ ./boost_test --help
Allowed options:
  --help                produce help message
  --compression arg     set compression level

bruce@bruce-K45VD:~/study/boost_study/build$ ./boost_test --compression 10
Compression level was set to 10.

多选项细化设计

当然,选项值可以具有除int之外的其他类型,并可以具有其他有趣的属性,我们继续进行讨论。

boost_test2.cpp

#include 
#include 
#include 
#include 

using namespace std;
namespace po = boost::program_options;

int main(int argc, char ** argv)
{
    int opt;
    po::options_description desc("Allowed options");
    desc.add_options()
    ("help", "produce help message")
    ("optimization", po::value<int>(&opt)->default_value(10), 
    "optimization level")
    ("include-path,I", po::value<string>(), 
    "include path")
    ("input-file", po::value<string>(), "input file");   

    po::positional_options_description p;
    p.add("input-file", -1);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).
          options(desc).positional(p).run(), vm);
    po::notify(vm); 

    if (vm.count("help")) {
        cout << desc << "\n";
        return 1;
    }

    if (vm.count("include-path"))
    {
        cout << "Include paths are: " 
         << vm["include-path"].as<string>() << "\n";
    }

    if (vm.count("input-file"))
    {
        cout << "Input files are: " << vm["input-file"].as<string>() << "\n";
    }
    cout << "Optimization level is " << opt << "\n";    
}

在该部分代码中,想象一下我们正在编写一个编译器。 它应该采用优化级别,许多包含路径和许多输入文件,并执行一些有趣的工作。

"help"选项同上一个例子类似,给我们提供一些输入配置的说明。

“optimization”选项显示了两个新功能。 首先,我们指定变量(&opt)的地址。 存储值之后,该变量将具有选项的值。 其次,我们指定默认值10,如果用户未指定任何值,将使用默认值。

“ include-path”选项是options_description类的接口仅服务于一个源(命令行)的唯一情况的示例。 用户通常喜欢将短选项名称用于通用选项,而“ include-path,I”名称则指定短选项名称为“ I”。 因此,“-include-path”和“ -I”都可以使用。

“input-file”选项指定要处理的文件列表。 可以这样来写:

compiler --input-file=a.cpp

更加规范的写法为:

compiler a.cpp

如上所述,没有选项名称的命令行标记被该库称为“positional options”。 它们也可以处理。 在用户的一点帮助下,库可以确定“ a.cpp”的真正含义与“ --input-file = a.cpp”相同。 但是需要通过一下代码来实现此功能:

po::positional_options_description p;
p.add("input-file", -1);

po::variables_map vm;
po::store(po::command_line_parser(ac, av).
          options(desc).positional(p).run(), vm);
po::notify(vm);

前两行说所有位置选项都应转换为“positional options”选项。 还要注意,我们使用command_line_parser类来解析命令行,而不是parse_command_line函数。 后者是简单情况下的便捷包装,但是现在我们需要传递其他信息。

运行结果:

bruce@bruce-K45VD:~/study/boost_study/build$ ./boost_test2 --help
Allowed options:
  --help                    produce help message
  --optimization arg (=10)  optimization level
  -I [ --include-path ] arg include path
  --input-file arg          input file
bruce@bruce-K45VD:~/study/boost_study/build$ ./boost_test2 --optimization 4 -I bruce/home a.cpp
Include paths are: bruce/home
Input files are: a.cpp
Optimization level is 4

多源文件设计

在命令行上为编译器指定所有选项很可能会比较麻烦。 理想的是创建一个具有通用设置的配置文件,该配置文件将与命令行一起使用。

当然,将需要组合命令行和配置文件中的值。 例如,在命令行上指定的优化级别应覆盖配置文件中的值。 另一方面,应该合并包含路径。

首先,我们声明options_description类的几个实例。 原因是,通常来说,并非所有选项都一样。 某些选项,例如上面的“input-file”,不应出现在自动帮助消息中。 一些选项仅在配置文件中有意义。 最后,在帮助消息中有一些结构,而不仅仅是一长串的选项。 这需要声明几个选项组,代码如下。

boost_test3.cpp

#include 
#include 
#include 
#include 

using namespace std;
namespace po = boost::program_options;

int main(int argc, char ** argv)
{
    int opt;
    // Declare a group of options that will be 
    // allowed only on command line
    po::options_description generic("Generic options");
    generic.add_options()
    ("version,v", "print version string")
    ("help", "produce help message")    
    ;
    
    // Declare a group of options that will be 
    // allowed both on command line and in
    // config file
    po::options_description config("Configuration");
    config.add_options()
    ("optimization", po::value<int>(&opt)->default_value(10), 
          "optimization level")
    ("include-path,I", 
         po::value<string>()->composing(), 
         "include path");

    // Hidden options, will be allowed both on command line and
    // in config file, but will not be shown to the user.
    po::options_description hidden("Hidden options");
    hidden.add_options()
    ("input-file", po::value<string>(), "input file");   

    po::options_description cmdline_options;
    cmdline_options.add(generic).add(config).add(hidden);

    po::options_description config_file_options;
    config_file_options.add(config).add(hidden);

    po::options_description visible("Allowed options");
    visible.add(generic).add(config);

    po::positional_options_description p;
    p.add("input-file", -1);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).
          options(cmdline_options).positional(p).run(), vm);
    po::notify(vm); 

    if (vm.count("help")) {
        cout << visible << "\n";
        return 1;
    }

    if (vm.count("include-path"))
    {
        cout << "Include paths are: " 
         << vm["include-path"].as<string>() << "\n";
    }

    if (vm.count("input-file"))
    {
        cout << "Input files are: " << vm["input-file"].as<string>() << "\n";
    }
    cout << "Optimization level is " << opt << "\n";   

}

注意在“ include-path”选项的声明中对composition方法的调用。 它告诉库,应该将来自不同来源的值组合在一起。options_description类的add方法可用于进一步对选项进行分组:

po::options_description cmdline_options;
cmdline_options.add(generic).add(config).add(hidden);

po::options_description config_file_options;
config_file_options.add(config).add(hidden);

po::options_description visible("Allowed options");
visible.add(generic).add(config);

值的解析和存储遵循通常的模式,除了我们另外调用parse_config_file,并两次调用store函数。 但是,如果在命令行和配置文件中都指定了相同的值,会发生什么呢? 通常,首选首先存储的值。 这就是“ --optimization”选项的情况。 对于“composing”选项(如“include-file”),将合并值。

运行结果:

bruce@bruce-K45VD:~/study/boost_study/build$ ./boost_test3 --help
Allowed options:

Generic options:
  -v [ --version ]           print version string
  --help                     produce help message

Configuration:
  --optimization arg (=10)   optimization level
  -I [ --include-path ] arg  include path

bruce@bruce-K45VD:~/study/boost_study/build$ ./boost_test3 --optimization 4 -I bruce/home a.cpp_b.cpp
Include paths are: bruce/home
Input files are: a.cpp_b.cpp
Optimization level is 4

第一次调用使用配置文件中的值。 第二次调用还使用命令行中的值。 可见,命令行和配置文件中的包含路径已合并,而优化是从命令行进行的。

CMakeLists文件

CMakeLists.txt

cmake_minimum_required( VERSION 2.8 )
project( boost_study )

set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )

find_package(Boost COMPONENTS program_options)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})

add_executable( boost_test boost_test.cpp  )
target_link_libraries( boost_test 
${Boost_PROGRAM_OPTIONS_LIBRARY}
 )

add_executable( boost_test2 boost_test2.cpp  )
target_link_libraries( boost_test2 
${Boost_PROGRAM_OPTIONS_LIBRARY}
 )

 add_executable( boost_test3 boost_test3.cpp  )
target_link_libraries( boost_test3 
${Boost_PROGRAM_OPTIONS_LIBRARY}
 )

参考链接:

boost官方使用说明
相关博客

你可能感兴趣的:(C++学习初步)