0

The code is as below. Since the number of parameters is different, the call should not be ambiguous. One of the constructors accepts a string and other string plus integer. Why do I get the error?

#include <iostream> #include <string> using namespace std; class AmbiguosCheck { public: AmbiguosCheck(string checkId = string(""), int length = 0) : checkId_(checkId), length_(length){} AmbiguosCheck(string xmlstring) { fromStringForInternalTransfer(xmlstring); } string checkId_; int length_; string toStringForInternalTransfer(){ return checkId_ + "|" + to_string(length_); } void fromStringForInternalTransfer(string xmlstring) { checkId_ = xmlstring; //Using simple assigment for sample code. Need to split, convert and assign the values. length_ = 20; } }; int main() { AmbiguosCheck bd((string)"Check ID|20.000"); } 

Compilation error:

In function 'int main()': 35:44: error: call of overloaded 'AmbiguosCheck(std::string)' is ambiguous 35:44: note: candidates are: 14:5: note: AmbiguosCheck::AmbiguosCheck(std::string) 9:5: note: AmbiguosCheck::AmbiguosCheck(std::string, int) 6:7: note: AmbiguosCheck::AmbiguosCheck(const AmbiguosCheck&) 6:7: note: AmbiguosCheck::AmbiguosCheck(AmbiguosCheck&&) 

And why are there 2 more candidates for ambiguity?

5
  • 1
    You have two constructors that can take a single std::string argument (the one taking an int argument have both the std::string and int arguments as optional). Which one should be used? Commented Jan 14, 2020 at 10:07
  • Does this answer your question? Ambiguity in c++ constructor when a constructor with default argument exists Commented Jan 14, 2020 at 10:08
  • I understand now, why I get the error. But I don't know how to solve this. Because the meaning of string are different in the two function. In the case AmbiguosCheck(string, int) its direct assignment to member variable. And when AmbiguosCheck(xmlstring) I want to split the string and assign the value after converting them. I have not done that in the sample code. Commented Jan 14, 2020 at 10:18
  • Perhaps you should rethink the design that lead to this code? For example by creating a small inheritance hierarchy where you have two child-classes that implements one way each? Or perhaps implement some kind of factory function (or a pair of them) to create the object? Commented Jan 14, 2020 at 10:36
  • I will dig more then. Commented Jan 14, 2020 at 10:41

2 Answers 2

1

The first constructor specifies a default value for the second int argument. This can hence be left out, which then leaves you with two constructors that both can be invoked with one std::string argument. This is indeed ambiguous.

To fix this, you can remove the = 0 default parameter, by passing the integral second argument as a (non-defaulted) std::optional<int> (C++17 is required, then) or go with named static factory functions.

Sign up to request clarification or add additional context in comments.

3 Comments

I understand now, why I get the error. But I don't know how to solve this. Because the meaning of string are different in the two function. In the case AmbiguosCheck(string, int) its direct assignment to member variable. And when AmbiguosCheck(xmlstring) I want to split the string and assign the value after converting them. I have not done that in the sample code.
Well, I tried to give you three options on how to fix that. Can you be specific about what part of those suggestions you don't understand?
I will give more context. What I wanted to do was to have two constructors. One which passes the values of class members to initialize the class members and the other which unpacks the values from a string. Right now I can do what I need to do by calling the default constructor and then calling the function fromStringForInternalTransfer. ` AmbiguosCheck bd; bd.fromStringForInternalTransfer("Check ID|20.000");` I wanted to do this directly in the constructor instead.
1

AmbiguosCheck(string checkId = string(""), int length = 0) AmbiguosCheck(string xmlstring)

So if you have AmbiguosCheck(myString) which is it to call?

AmbiguosCheck(myString, 0); // first constructor, because length = 0 default AmbiguosCheck(myString); // second single argument constructor 

Does having the second constructor actually makes sense? If length = 0 is a proper default, just keep that one.

Otherwise maybe get rid of the default values, and have a default constructor.

AmbiguosCheck() { ... } AmbiguosCheck(string xmlstring) { ... } AmbiguosCheck(string checkId, int length) { ... } 

Which can all be called unambiguously.

AmbiguosCheck a; // default constructor () AmbiguosCheck b(myString); // string AmbiguosCheck c(myString, n); // string, int 

2 Comments

I understand now, why I get the error. But I don't know how to solve this. Because the meaning of string are different in the two function. In the case AmbiguosCheck(string, int) its direct assignment to member variable. And when AmbiguosCheck(xmlstring) I want to split the string and assign the value after converting them. I have not done that in the sample code.
Well then use the form without default parameters, you will just have to do AmbiguosCheck(myString, 0) explicitly if you want the int version with a zero, but you need something explicit to tell them apart, the compiler can't guess from other context. An alternative that might be far less confusing would be "named constructors".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.