今天看boost库,发现一个很有意思的东西,
boost::program_options::options_description desc("Allowed Options");
desc.add_options()
("help", "Produce Help")
("compression", po::value<int>(), "Set compression Level");
这个add_options后边的参数个数是不确定的,例如你可以加多个参数,
desc.add_options()
("help", "Produce Help")
("command1", "command1 test")
("command2", "command2 test")
("command3", "command3 test")
("command4", "command4 test")
("command5", "command5 test")
("command6", "command6 test")
("command7", "command7 test");
刚看到的时候一下子没看懂,感觉这好像不是我所理解的C++,这种玩意能通过编译???
仔细想想,查了下boost的源代码,add_options声明如下:
options_description_easy_init add_options();
add_options方法返回一个options_description_easy_init对象,而options_description_easy_init定义如下:
class options_description_easy_init {
public:
options_description_easy_init(options_description* owner);
options_description_easy_init&
operator()(const char* name,
const char* description);
options_description_easy_init&
operator()(const char* name,
const value_semantic* s);
options_description_easy_init&
operator()(const char* name,
const value_semantic* s,
const char* description);
private:
options_description* owner;
};
看到没有,核心是options_description_easy_init重载了operator(), 并返回本身的引用,
这样,每次调用operator()运算符之后的返回可以继续调用operator(),通过这样的方法实现了参数可变个数。
以前自己也实现过类似的功能,通过宏来实现,远不如这种方法优雅。
第一次看到这样的用法,也许我火星了,深切感受到boost的强大之处阿。
附上例程源代码:
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include <iostream>
#include <iterator>
using namespace std;
int main(int argc, char* argv[]) {
try {
po::options_description desc("Allowed Options");
desc.add_options()
("help", "Produce Help")
("compression", po::value<int>(), "Set compression Level");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
if(vm.count("help")) {
cout << desc << "\n";
return 1;
}
else if(vm.count("compression")) {
cout << "Compression level was set to "
<< vm["compression"].as<int>() << "==\n";
}
else {
cout << "Compression level was not set\n";
}
}
catch(exception& e) {
cerr << "error: " << e.what() << "\n";
return 1;
}
catch(...) {
cerr << "Exception of unknown type!\n";
}
return 0;
}
另附用宏实现的代码:
// Constants defintions for parameters
#define MAX_CMD_PARM_NUM 20
#define MAX_CMD_PARM_LEN 64
enum ArgType
{
ARG_INT = 0,
ARG_LONG,
ARG_DOUBLE,
ARG_STRING
};
struct ArgRec
{
enum ArgType argType;
void* argValue;
const char* argDefValue;
const char* argDesc;
};
// {{ Types definiton for command parser
#define CMD_MAP_BEGIN(cmdDesc, cmdLine) \
ArgRec argTable[] = {
#define CMD_INT_ARG(storage, def, desc) \
{ARG_INT, storage, def, desc},
#define CMD_LONG_ARG(storage, def, desc) \
{ARG_LONG, storage, def, desc},
#define CMD_DOUBLE_ARG(storage, def, desc) \
{ARG_DOUBLE, storage, def, desc},
#define CMD_STRING_ARG(storage, def, desc) \
{ARG_STRING, storage, def, desc},
#define CMD_BOOL_ARG(storage, def, desc) \
{ARG_BOOL, storage, def, desc},
#define CMD_MAP_END() \
}; \
size_t narg = sizeof(argTable)/sizeof(struct ArgRec); \
parserCmd(cmdLine, argTable, narg);
// }}
void parserCmd(const char* cmdLine, struct ArgRec* argRec, int narg)
{
char param[MAX_CMD_PARM_NUM][MAX_CMD_PARM_LEN];
int i;
int k;
int j = 0;
bool seenQuota = FALSE;
bool seenSpace = FALSE;
int len = (int)strlen(cmdLine);
const char* curValue = NULL;
int* intVal;
long* longVal;
double* dblVal;
bool* boolVal;
memset(param, 0, sizeof(param));
for (i = 0, k = 0; i < len; i++) {
if (cmdLine[i] == '\"') {
if (!seenQuota) {
j++;
k = 0;
}
seenQuota = !seenQuota;
continue;
}
if (!seenQuota) {
if (cmdLine[i] == '(' ||
cmdLine[i] == ',' ||
cmdLine[i] == ' ' ||
cmdLine[i] == ')' ||
cmdLine[i] == '\t' ||
cmdLine[i] == '<')
{
seenSpace = TRUE;
continue;
}
if (seenSpace) {
seenSpace = FALSE;
j++;
k = 0;
}
}
param[j][k++] = cmdLine[i];
}
for (i = 0; i < narg; i++) {
if (j >= i + 1) curValue = param[i + 1];
if (!curValue) {
curValue = argRec[i].argDefValue;
}
switch (argRec[i].argType) {
case ARG_INT:
intVal = (int*)argRec[i].argValue;
*(intVal) = atoi(curValue);
break;
case ARG_LONG:
longVal = (long*)argRec[i].argValue;
*(longVal) = atol(curValue);
break;
case ARG_DOUBLE:
dblVal = (double*)argRec[i].argValue;
*(dblVal) = atof(curValue);
break;
case ARG_STRING:
strcpy((char*)argRec[i].argValue, curValue);
break;
default:
printf("Error: Unkown parameter type:%d\n", argRec[i].argType);
break;
}
curValue = NULL;
}
使用:
bool executeCommand(const char* command, const char* cmdLine)
{
if (strcasecmp(command, "ResPerCall") == 0) {
CMD_MAP_BEGIN("ResPerCall", cmdLine)
CMD_INT_ARG(&g_resultPerCall, "100", "Result per call")
CMD_MAP_END()
return true;
}
//...................
return false;
}
分享到:
相关推荐
AWR1443boost用户指南笔记1
Boost 模板元编程学习笔记(二),开始你模板元编程的历程。C++,模板,标准库,元编程,教程,笔记
本笔记是全面认识开关电源BUCK BOOST参考笔记,值得下载收藏
面向开发人员的直观,时尚的笔记应用程序。 离线写入 即使您处于离线状态,也可以在笔记本电脑上书写/编辑笔记。 多个设备 Boostnote可用于浏览器,台式机和移动设备。 语法重点 Boostnote可以突出显示100多种...
Boostnote是一款采用ElectronJs开发的开源笔记应用
Boost是C++标准库开发人员参与编写的,非常好。里面有各种数组、线程池、通信库等,是Linux、Window通用的东西。不学他,就落伍了。
该文件是基于UC3842的boost电路的设计及仿真,包括电路图,相应的仿真参数,和一些应用笔记以及调试的一些心得
本文总结了CRM模式BOOST拓扑结构实现PFC的学习笔记,希望本章的内容对大家学习PFC能够有所帮助
64位 VS2010 配置Boost库,这是学习Boost标准库开发的基础。
boost库基本使用方法,使用cmake2.6构建工程,包含nocopyable\singleton\asio\filesystem\bind\thread\futuer等
图片太多懒得一张张保存再分享了,所以就把学习的笔记文档分享出来。 主要来源:https://zhuanlan.zhihu.com/p/633235266 https://blog.csdn.net/qlexcel/article/details/78920902
Mac版本的boostnote,boostnote官网下载很慢已打包。可以直接下载安装使用,记录笔记等非常方便,可以导出导入多种格式
光伏发电+boost+储能+双向dcdc+并网逆变器控制(低压用户型电能路由器仿真模型)【含个人笔记+建模参考】 包含Boost、Buck-boost双向DCDC、并网逆变器三大控制部分 boost电路应用mppt, 采用扰动观察法实现光能...
如果你是一名编程员,你一定记下了非常多在你脑中...为了保证你可以有秩序地保存这些笔记,你需要一个为开发者量身定做的软件。 这就是‘Boost Note’ https://boostnote.io/ ,一个面向开发者直观且美观的记号编辑器。
Boost是一个功能强大、构造精巧、跨平台、开源并且完全免费的C++程序库,有着“C++‘准’标准库”的美誉。 Boost由C++标准委员会部分成员所设立的Boost社区开发并维护,使用了许多现代C++编程技术,内容涵盖字符串...
这段代码为数组提供了一个非常薄的包装器,使它们可以在 C++ 中作为对象进行访问。 在可能的情况下,不会复制数据本身,即使数据不连续也是... 笔记 此代码目前处于实验阶段,缺乏足够的文档和单元测试。 先决条件 Boo
我们为开发人员团队开发了一个名为“ Boost Hub”的协作工作区应用程序。 它是可定制的,易于为您的团队进行优化,例如乐高积木,甚至可以让您实时一起编辑文档! 带有GitHub Flavored Markdown的Polished Notes应用...
程序员常用Markdown笔记软件,有一个问题就是它的滚动条自动上浮问题待解决
common[.cpp .h] 定义Caffe类internal_thread[.cpp .h] 使用boost::thread线程库net[.cpp .h]