Reputation: 317
I have a few functions defined which have return types of void, int, float, float*, etc(some classes aswell).
My cmd is a vector of strings inputed from user. 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.
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'
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
Upvotes: 3
Views: 427
Reputation: 20386
The return type of a function must be able to be determined at compile-time. C++ is a statically-typed language. auto
does not mean "could be anything", it means "will be deduced at compile-time".
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).
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):
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&) {}
}
An alternate version, as suggested by @chris, uses std::monostate
to avoid the use of 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&) {}
Upvotes: 9