boost笔记1 J#
程序员文章站
2022-07-03 20:27:11
...
今天看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; }