天天看点

boost::program_options

作用:

它是一个C++解析命令行的库。它使用命令行和配置文件对程序选项进行设置。该库有错误检查机制,它的选项值可从命令行,配置文件以及环境变量中提取。

要解析一个命令行选项,需要以下三步:

1.定义命令行选项。取名且设置值。若一个命令行选项解析为键/值对,还需要设置值的类型,比如是一个字符串还是一个数字

2.用解析器去解析命令行。从main()的两个参数中获取命令行,argc与argv

3.存储由解析器解析好的命令行选项。boost.program_options库从std::map中派生了一个类可用来存储命令行选项的键/值对。随后,可检查哪个选项已经被存储以及它们的值是什么

样例:

#include <boost/program_options.hpp>
#include <iostream>

using namespace std;
using namespace boost::program_options;


void on_age(int age)
{
	std::cout << "On age: " << age << "\n";
}

int main(int argc, const char  *argv[])
{
	try
	{
		options_description desc{ "Options" };
		desc.add_options()
			("help,h", "Help screen")
			("pi", value<float>()->default_value(3.14f), "Pi")
			("age", value<int>()->notifier(on_age), "age");
		variables_map vm;
		store(parse_command_line(argc, argv, desc), vm);
		notify(vm);

		if (vm.count("help"))
			std::cout << desc << '\n';
		else if (vm.count("age"))
			std::cout << "Age: " << vm["age"].as<int>() << '\n';
		else if (vm.count("pi"))
			std::cout << "Pi: " << vm["pi"].as<float>() << '\n';
	}
	catch (const error &ex)
	{
		std::cerr << ex.what() << '\n';
	}

}
           

输出:

boost::program_options

因此,要使用Boost.ProgramOptions,需要包含头文件boost/program_options.hpp,以及在编译时要添加类似的库目录boost_1_62_0\lib64-msvc-12.0以包含lib文件。使用命令空间:boost::program_options

类boost::program_options::options_description用来描述命令行。该类型的对象会写入类似std::cout流用来显示可变命令行的选项(上例中.\test.exe -h所显示的)。字符串传入该结构中充当命令行名字的角色。boost::program_options::options_description它定义了一个成员函数add()来接收本身类型的参数。可调用该函数来描述每个命令行选项。上例中调用add_options()来做这件事情,但不是每条命令行选项都用它来做,只是它用起来更方便而已。

add_options()返回一个代理对象用来代表类boost::program_options::options_description的一个对象。该代理对象的类型没毛病,更有意思的是该代理对象简化定义了许多命令行选项。它使用operator()重载函数来得到想要的数据去定义一个命令行。该重载操作会返回一个引用给代理对象,它允许重复调用operator()。

上例中在代理对象options_description的帮助下定义了三个命令行选项:

第一个命令行是:--help。该命令行描述设置为“Help screen”。该选项是一个开关,不是键值对。在命令行设置--help或忽略它。不可能给--help设置一个值。

需要注意的是第一个传往operator()的字符串是“help,h”。可为命令行选项指定短的名字。短名只由一个字母构成且在逗号后面。因此,现在输入--help或者输入-h都能显示help选项。

除了--help,还有两个命令行选项,--pi和--age。它们不是开关,它们是键值对。--pi和--age都希望能够设置一个值。

传入boost::program_options::value_semantic类型的对象指针作为operator()的第二个参数来定义一个选项的键值对。不需要直接访问boost::program_options::value_semantic。可使用辅助函数boost::program_options::value()来创建一个boost::program_options::value_semantic类型的对象。boost::program_options::value()会返回该对象的地址,传入operator()的代理对象。

boost::program_options::value()是一个函数模板把命令行选项类型作为模板参数。因此,命令行--age希望得到一个整型以及--pi希望得到一个浮点数。

从boost::program_options::value()返回的对象提供了一些成员函数。比如,default_value()用来设定默认值。比如如果没有在命令行再设置--pi,则默认就设置为了3.14

notifier()链接一个函数到命令行选项的值。随后命令行选项的值会调用该函数。上例中,函数on_age()与--age相连。若命令行选项--age被用来设置一个age,则该age会被传入on_age()后写入标准输出流。

使用类似on_age()的函数来处理数值是可选的。由于还可以使用其他方式来访问数据所以就不一定非要用notifier()。

所有的命令行选项定义后,就需要使用一个解析器了。上例中,辅助函数boost::program_options::parse_command_line()被调用来解析命令行。函数使用argc与argv参数来定义命令行以及desc用来存储选项描述符。

boost::program_options::parse_command_line()以boost::program_options::parsed_options类型的对象的方式返回解析的命令行选项。一般不用直接访问这个对象,而是将它们传入函数boost::program_options::store()中使用容器将它们保存起来。

上例中,传入vm作为boost::program_options::store()的第二个参数,vm是一个boost::program_options::variables_map类型的对象,该对象由std::map<std::string, boost::program_options::variable_value> 派生而来的。并且,因此它也会提供与std::map相同的函数。比如,可以调用count()来检查某个命令行选项是否已经被使用且被保存在容器中。

在上例中,在count()被调用以及vm被读取之前,boost::program_options::notify()被调用了。该函数会触发其他函数的调用,比如on_age(),它是被notifier()函数链接到一个值的。没有boost::program_options::notify()函数,on_age()不会被调用。

vm可用来检查命令行选项是否存在容器中,且可用来读取设置给命令行选项的值。vm的类型是boost::program_options::variable_value,它是一个在内部使用了boost::any的类。

因此,可以从它的成员函数value()中获取到boost::any类型的对象。

上例中,调用as(),而不是value(),是因为该成员函数会将命令行选项的值转换成模板参数传入的类型.as()使用boost::any_cast()来进行类型转换。

一定要确保传入as()的类型与命令行选项的类型匹配。比如,上例中,命令行选项--age希望设置为一个整型值,因此int型必须作为模板参数类型传给as().

解释结果:

.\test.exe

在这种情况下,显示的是Pi:3.14。是因为命令行中没有设置参数为--pi,也因此显示的为默认值。

.\test.exe --pi 3.1415

使用--pi参数设置值时

.\test.exe --pi 3.1415 --age 29

使用了--pi以及--age设置值时。当boost::program_options::notify()被调用时,第一行On age: 29被写入;因为它触发了on_age()函数的执行。而--pi则没有输出,因为程序使用else if语句导致不再执行--pi。

.\test.exe -h

可查看所有的命令行选项。

可使用两种方式查看--help与-h。而--pi则是显示了默认的属猪。命令行选项以及它们的描述符都自动格式化了。只需要将类型为boost::program_options::options_description的对象写入标准输出流即可。

.\test.exe --age

由于--age选项没有设置具体的值。因此boost::program_options::parse_command_line()抛出异常boost::program_options::error。该异常被捕获到,因此一个错误消息写入标准输出流。

boost::program_options::error从std::logic_error派生而来。

Boost.ProgramOptions自定义了一些额外的异常类,都是派生自boost::program_options::error。其中一个异常就是boost::program_options::invalid_syntax,它就是上例中抛出的异常,在没有给--age设置一个值时。

---------------------------------------------------------------------------------------------------------20170728 end.