简体   繁体   English

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

[英]Deduce return type of a function dynamically

I have a few functions defined which have return types of void, int, float, float*, etc(some classes aswell). 我定义了一些函数,它们返回类型为void,int,float,float *等(某些类也是如此)。

My cmd is a vector of strings inputed from user. 我的cmd是一个从用户输入的字符串向量。 where 0th location is the function name(read_lib, square, open_file) and the 1st location is the argument(/path/to/file , number_to_square) etc. 其中第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
}

Error: inconsistent deduction for 'auto': 'unsigned int' and then 'Pin' 错误:'auto'扣除不一致:'unsigned int'然后'Pin'

Edit: I have another question. 编辑:我有另一个问题。 All my functions do not take in string input as argument. 我的所有函数都没有将字符串输入作为参数。 I could convert string to integer but how do I convert it to some class object like Pin/Cell 我可以将字符串转换为整数但是如何将其转换为某些类对象,如Pin / Cell

The return type of a function must be able to be determined at compile-time. 必须能够在编译时确定函数的返回类型。 C++ is a statically-typed language. C ++是一种静态类型的语言。 auto does not mean "could be anything", it means "will be deduced at compile-time". auto并不意味着“可以是任何东西”,它意味着“将在编译时推断”。

If you have a function which needs to potentially return multiple types, you'll want to use std::variant (in C++17) or boost::variant (pre-C++17, but requires use of the Boost Library). 如果你有一个需要潜在返回多个类型的函数,你将需要使用std::variant (在C ++ 17中)或boost::variant (在C ++ 17之前,但需要使用Boost Library) )。

In your case specifically, since some of your calls can return nothing (as demarcated by void ), it might also be good to place this variant inside an optional (also C++17, or boost::optional if pre-C++17): 在具体的情况下,由于你的一些调用什么都不返回(由void划分),将这个变量放在一个optional (也就是C ++ 17,或者如果pre-C ++的boost::optional )中也可能是好的。 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&) {}
}

EDIT: 编辑:

An alternate version, as suggested by @chris, uses std::monostate to avoid the use of std::optional . @chris建议的备用版本使用std::monostate monostate来避免使用std::optional This may be a better interface for you, depending on the circumstances. 根据具体情况,这可能是一个更好的界面。

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&) {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM