天天看點

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.

繼續閱讀