0

I've overloaded my function contains three times

// returns true if char c is contained in unordered map um bool contains(std::unordered_map<char, op>& um, char c){ return um.find(c) != um.end(); } // returns true if string s is contained in unordered map um bool contains(std::unordered_map<char, op>& um, std::string& s){ return s.length() == 1 && contains(um, s[0]); } // returns true if string s is contained in unordered map um bool contains(std::unordered_map<std::string, func>& um, std::string& s){ return um.find(s) != um.end(); } 

The parameters are different in each overloaded function. Yet, from the line (contains(opmap, q_front)) I get the error: more than one instance of overloaded function "contains" matches the argument list.

For reference, opmap is of type std::unordered_map<char, op>, and q_front is a string. op in this case is just struct I created- I can post if needed, but I feel it is unnceessary in this case.

My question is why I'm getting this error, as the function call above should uniquely call the second method header: bool contains(std::unordered_map<char, op>& um, std::string& s){ because of the type of opmap matches the first parameter, and the type of q_front is string.

UPDATE:

Full error message:

more than one instance of overloaded function "contains" matches the argument list: -- function "contains(std::unordered_map<char, op, std::hash<char>, std::equal_to<char>, std::allocator<std::pair<const char, op>>> &um, std::string s)" (declared at line 48 of "/Users/raleighclemens/Documents/Calc_cpp/calc.h") -- function "contains(std::unordered_map<char, op, std::hash<char>, std::equal_to<char>, std::allocator<std::pair<const char, op>>> &um, std::string &s)" (declared at line 49) -- argument types are: (std::unordered_map<char, op, std::hash<char>, std::equal_to<char>, std::allocator<std::pair<const char, op>>>, std::string)C/C++(308) 

MRE:

#include <iostream> #include <string> #include <functional> #include <unordered_map> #define LEFT 0 #define RIGHT 1 #define UNARY 0 #define BINARY 1 struct op{ char symbol; uint8_t precedence; uint8_t assoc; uint8_t type; std::function<double (double, double)> ashley; }; struct func{ std::string symbol; uint8_t type; std::function<double (double, double)> ashley; }; bool contains(std::unordered_map<char, op>& um, char c){ return um.find(c) != um.end(); } // returns true if string s is contained in unordered map um bool contains(std::unordered_map<char, op>& um, std::string& s){ return s.length() == 1 && contains(um, s[0]); } // returns true if string s is contained in unordered map um bool contains(std::unordered_map<std::string, func>& um, std::string& s){ return um.find(s) != um.end(); } int main(int argc, char** argv){ std::unordered_map<char, op> opmap; op op1{'+', 2, LEFT, BINARY, [=] (double a, double b){return a + b;}}; opmap.emplace('+', op1); std::cout << contains(opmap, "+"); 
11
  • 4
    Can you provide a minimal reproducible example and the exact error message? Commented Jul 20, 2021 at 20:45
  • 3
    Your code contains multiple problems that are probably unrelated, like the use of non-const references for no good reason. Also, you failed to include the entire error message text; that is a bad idea. You might not understand the error, but the error will describe your problem. Include it in a quoted code block. Third, a minimal reproducible example would be very useful, and make solving your problem easy. Commented Jul 20, 2021 at 20:47
  • 2
    Anyway, it turns out to be pretty important to use const std::string& s instead of std::string& s, because the former allows you to pass temporaries as arguments. In your case you have a temporary that isn't even a std::string, it's a const char[2]. Commented Jul 20, 2021 at 21:08
  • 1
    A char array is conceptually a string, but there are many technical differences between one and the actual class std::string. As for the const thing being important, here's a good question on the matter. Commented Jul 20, 2021 at 21:14
  • 1
    The error message clearly shows the ambiguous overloads are contains(std::unordered_map<char, op> &um, std::string s) and contains(std::unordered_map<char, op> &um, std::string &s), but there is no overload with a non-reference std::string s parameter in the code shown. Commented Jul 20, 2021 at 21:29

1 Answer 1

3

Which overload you expect to match your call to the below line?

std::cout << contains(opmap, "+"); 

Overload 1 cannot match, because of your second argument, i.e. "+". Its type is const char[2] and cannot be matched to char.

Overload 2 and 3 cannot match, because the type of "+" has a const qualifier, but in those two overloads your string is passed as a non-const reference.

So, to fix your issue, you should either:

  • change "+" to '+' to use the first overload.
  • change std::string & to const std::string & to use overload 2.
Sign up to request clarification or add additional context in comments.

6 Comments

thanks! but why is "+" implicitly type const char* and not std::string? also why can a const char* be implicitly cast into const std::string but not std::string?
@rjc810 You're missing that it's const std::string& and std::string&, that is to say references.
@rjc810 "+" is a string literal, its type is const char[2], which decays into a const char* in some contexts. std::string has a non-explicit constructor that accepts a const char*, so you can pass a const char[N] into a (const) std::string or const string& variable/parameter, but not to a non-const std::string& reference. If you want "+" to be a string, use contains(opmap, string("+")) or using std::literals::string_literals; contains(opmap, "+"s) instead
@RemyLebeau Thanks for the precise clarifications ;)
@RemyLebeau contains(opmap, string("+")) would have the same problem where you can't bind a prvalue to a non-const reference, wouldn't it? You'd still have to change the function signature, at which point "+" itself would work.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.