欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
}

 

相关标签: J#