【问题标题】:Ambiguous constructor between list<string> and stringlist<string> 和 string 之间有歧义的构造函数
【发布时间】:2017-04-05 23:48:54
【问题描述】:

在以下代码中,当我尝试将列表传递给构造函数时,编译器给了我一个错误:

#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;
}

我尝试将explicit 添加到构造函数的声明中,但它并没有改变任何东西。

【问题讨论】:

  • MyClass c2({{"azerty"}, {"qwerty"}}); ?
  • @WhozCraig:是的,它正在工作,但为什么我必须添加额外的大括号?有没有办法删除它们以提高可读性?
  • 因为std::string's 9th constructor overload 有一个初始化列表。
  • @Gill 错误的构造函数。那个不匹配

标签: c++ constructor


【解决方案1】:

问题是string有这个构造函数:

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

其中{"azerty", "qwerty"} 是一个不幸的匹配,因为const char* 实际上是一个输入迭代器......即使这两个参数不打算成为迭代器,也不是进入同一个容器的迭代器。

一种解决方案是只提供一个构造函数,该构造函数接受一个初始化列表并只使用该构造函数:

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

【讨论】:

  • 确实,有 3 个字符串,没有歧义。但是我添加MyClass(const char *) 的解决方案让我像这样使用它:MyClass c1("foobar");。这是一个细节,但是当有许多对象要构造时,它提高了可读性,几乎所有对象都只有一个字符串。
  • @yolenoyer 如果你想走那条路,我建议MyClass(string )MyClass(initializer_list&lt;string&gt; )
  • 谢谢,它是这样工作的!即使不完全了解所有细节,尤其是关于initializer_list 类...我稍后会看文档,再次感谢
【解决方案2】:

避免这种模棱两可的调用的一种方法是这样做,

     std::list<std::string> strList{"azerty", "qwerty"};
     MyClass c2(strList);

而不是

     MyClass c2({"azerty", "qwerty"});

【讨论】:

    【解决方案3】:

    正如人们在 cmets 中所说,这是因为 std::string 的构造函数重载之一有一个初始化列表。

    可以通过添加额外的大括号来修复它:

    MyClass c2({{"azerty"}, {"qwerty"}});
    

    当我在寻找可读性时,我找到了一种解决方法,方法是用这个更改字符串构造函数:

     MyClass(const char *str) : strings({str}) {}
    

    现在我可以做这两种结构了:

    MyClass c1("foobar");
    MyClass c2({"azerty", "qwerty"});
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-04
      • 2014-05-04
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多