yolenoyer yolenoyer - 1 month ago 6
C++ Question

Ambiguous contructor between list<string> and string

In the following code, the compiler gives me an error when I try to pass a list to the constructor:

#include <string>
#include <iostream>
#include <list>


class MyClass {
std::list<std::string> strings;

public:
void disp() {
for (auto &str : strings)
std::cout << str << std::endl;
}

MyClass(std::string const &str)
: strings({str}) {}

MyClass(std::list<std::string> const &strlist)
: strings(strlist) {}
};


int main ()
{
// Compiles well:
MyClass c1("azerty");
c1.disp();

// Compilation error, "call to constructor of 'MyClass' is ambiguous":
MyClass c2({"azerty", "qwerty"});
c2.disp();

return 0;
}


I tried to add
explicit
to the constructors' declarations, but it dosen't change anything.

How can I solve this?

Answer

The problem is that string has this constructor:

template< class InputIt >
basic_string( InputIt first, InputIt last, 
              const Allocator& alloc = Allocator() );

which {"azerty", "qwerty"} is an unfortunate match for because const char* is, in fact, an input iterator... even if the two arguments aren't intended to be iterators and aren't iterators into the same container.

One solution would be to just provide a single constructor that takes an initializer list and just use that one:

MyClass(std::initializer_list<std::string> il)
    : strings(il.begin(), il.end())
{ }
Comments