动态地推断函数的返回类型

时间:2017-09-21 16:07:18

标签: c++ c++11 c++14

我定义了一些函数,它们返回类型为void,int,float,float *等(某些类也是如此)。

我的cmd是一个从用户输入的字符串向量。其中第0个位置是函数名称(read_lib,square,open_file),第一个位置是参数(/ path / to / file,number_to_square)等。

auto find_and_execute(vector<string> cmd){
//for(auto x: cmd){cout << x << endl;}
if(cmd.at(0) == "square") {return square(stoi(cmd.at(1)));} // unsigned_int
if(cmd.at(0) == "cube") {return cube(stoi(cmd.at(1)));}     // unsigned_int
if(cmd.at(0) == "open_file") {open_file(cmd.at(1));}        //void
if(cmd.at(0) == "read_lib") {read_lib(cmd.at(1));}          //void
if(cmd.at(0) == "read_verilog") {read_verilog(cmd.at(1));}  //void
if(cmd.at(0) == "set_top") {set_top(cmd.at(1));}            //void
if(cmd.at(0) == "get_pin") {return get_pin(cmd.at(1));}     // Pin Class object takes in cell argument
}

错误:&#39; auto&#39;:&#39; unsigned int&#39;然后&#39; Pin&#39;

编辑:我有另一个问题。我的所有函数都没有将字符串输入作为参数。我可以将字符串转换为整数但是如何将其转换为某些类对象,如Pin / Cell

1 个答案:

答案 0 :(得分:9)

必须能够在编译时确定函数的返回类型。 C ++是一种静态类型的语言。 auto并不意味着&#34;可以是任何东西&#34;,它意味着&#34;将在编译时推断出#34;。

如果你有一个需要潜在返回多种类型的函数,你将要使用std::variant(在C ++ 17中)或boost::variant(在C ++ 17之前,但需要使用Boost Library。

在具体情况下,由于您的某些调用无法返回任何内容(由void划分),因此将此变体放在optional(也是C ++ 17,或boost::optional如果预先C ++ 17):

using return_t = std::optional<std::variant<unsigned int, Class>>;

return_t find_and_execute(std::vector<std::string> const& cmd) {
    if(cmd.at(0) == "square") {return square(stoi(cmd.at(1)));} // unsigned_int
    if(cmd.at(0) == "cube") {return cube(stoi(cmd.at(1)));}     // unsigned_int
    if(cmd.at(0) == "open_file") {open_file(cmd.at(1)); return {};}        //void
    if(cmd.at(0) == "read_lib") {read_lib(cmd.at(1)); return {};}          //void
    if(cmd.at(0) == "read_verilog") {read_verilog(cmd.at(1)); return {};}  //void
    if(cmd.at(0) == "set_top") {set_top(cmd.at(1)); return {};}            //void
    if(cmd.at(0) == "get_pin") {return get_pin(cmd.at(1));}     // Class object
}

return_t result = find_and_execute({std::string("square"), std::string("13")});
if(result) {//Should always be true
    try {
        unsigned int & value = std::get<unsigned int>(*result);
    } catch (std::bad_variant_access const&) {}
}

result = find_and_execute({std::string("open_file"), std::string("File.txt")});
if(!result) {//Should always be true
    /*...*/
}

result = find_and_execute({std::string("get_pin"), std::string("EAX")});
if(result) {//Should always be true
    try {
        Class & value = std::get<Class>(*result);
    } catch (std::bad_variant_access const&) {}
}

编辑:

@ chris建议的替代版本使用std::monostate来避免使用std::optional。根据具体情况,这可能是一个更好的界面。

using return_t = std::variant<std::monostate, unsigned int, Class>;

return_t find_and_execute(std::vector<std::string> const& cmd) {
    if(cmd.at(0) == "square") {return square(stoi(cmd.at(1)));} // unsigned_int
    if(cmd.at(0) == "cube") {return cube(stoi(cmd.at(1)));}     // unsigned_int
    if(cmd.at(0) == "open_file") {open_file(cmd.at(1)); return {};}        //void
    if(cmd.at(0) == "read_lib") {read_lib(cmd.at(1)); return {};}          //void
    if(cmd.at(0) == "read_verilog") {read_verilog(cmd.at(1)); return {};}  //void
    if(cmd.at(0) == "set_top") {set_top(cmd.at(1)); return {};}            //void
    if(cmd.at(0) == "get_pin") {return get_pin(cmd.at(1));}     // Class object
}

return_t result = find_and_execute({std::string("square"), std::string("13")});
try {
    unsigned int & value = std::get<unsigned int>(result);
} catch (std::bad_variant_access const&) {}

result = find_and_execute({std::string("open_file"), std::string("File.txt")});
//Could query for it if you really needed to
//try {
    //std::monostate & value = std::get<std::monostate>(result);
//} catch (std::bad_variant_access const&) {}

result = find_and_execute({std::string("get_pin"), std::string("EAX")});
try {
    Class & value = std::get<Class>(*result);
} catch (std::bad_variant_access const&) {}