yolenoyer yolenoyer - 9 months ago 49
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;

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");

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

return 0;

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

How can I solve this?

Answer Source

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