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.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官方使用说明
相关博客