Parsing commands using map<const string, function<? (?)>> commands;

瘦欲@ 提交于 2019-12-11 20:22:37

问题


Problem statement:

Given the interactive input, call the appropriate methods on appropriate objects (Bank, BankRegister, BasicAccount, etc...).

input (each command on a separate line):

create_bank <bank_name>\n
create_customer <bank_number> <customer_name>\n
create_account <bank_number> <customer_number>\n
deposit <amount> <account_number>/<bank_number>\n
etc...

Proposed solution:

#include <functional>

bool create_bank(const string& arguments){
    const string& bankName = arguments; //no need to parse here
    bankRegister.registerBank(new Bank(bankName,
                                       &bankRegister)); //can't access bankRegister!
    return true;
}

int main(){
    map<string, function<bool (string)>> commands;
    commands.emplace("create_bank",create_bank);
    ...
    BankRegister bankRegister;

    string command, arguments;
    cin>>command;
    getline(cin, arguments);
    commands[command](arguments);
    ...
}

Why it does not work:

  1. The bankRegister object can't be accessed from the functions. I might pass it by constant reference to the functions, but only some functions need it. I was thinking of making its members (m_banks, m_next_bankNumber) static, but then I would have to make them public, which is probably a bad design decision.
  2. Where should the argument parsing happen? Is it OK this way?
  3. What should the return value represent?

    a) arguments parsed successfully

    b) arguments parsed successfully and command executed successfully

    I use the exceptions for some of the errors, but some are silent except for cerr.

  4. Could I use variadic functions here to parse the arguments?

  5. Is there something else you would improve?

回答1:


You could change the signature of the create_bank function and use std::bind to bind the BankRegister argument, creating a function object with the call signature bool(const string&)

bool create_bank(const string& arguments, BankRegister& bankRegister){
    const string& bankName = arguments; //no need to parse here
    bankRegister.registerBank(new Bank(bankName,
                                       &bankRegister));
    return true;
}

int main(){
    BankRegister bankRegister;
    map<string, function<bool (string)>> commands;
    using std::placeholders::_1;
    commands.emplace("create_bank",std::bind(create_bank, _1, std::ref(bankRegister)));

You can do the same thing with a lambda function:

    commands.emplace("create_bank", [&bankRegister](const string& args) { return create_bank(args, bankRegister); });

The function object returned by bind and the closure object created by the lambda expression both have the required call signature, bool(const string&), but they also contain a reference to the bankRegister object and can pass it to create_bank




回答2:


Just use fancy code here:

#include <functional>
#include <string>
#include <map>

struct BankRegister {
  void create_bank(const std::string& name);
};

void handle_new_bank(BankRegister* reg, const std::string& name) {
  reg->create_bank(name);
}


int main() {
    std::map<std::string, std::function<void (const std::string)> > cmds;

    BankRegister reg;

    cmds.emplace("new_bank", std::bind(&handle_new_bank, &reg, std::placeholders::_1));
}


来源:https://stackoverflow.com/questions/33963808/parsing-commands-using-mapconst-string-function-commands

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!