为啥初始化列表中的元素数量会导致模棱两可的调用错误?

Posted

技术标签:

【中文标题】为啥初始化列表中的元素数量会导致模棱两可的调用错误?【英文标题】:Why does the number of elements in a initializer list cause an ambiguous call error?为什么初始化列表中的元素数量会导致模棱两可的调用错误? 【发布时间】:2017-05-21 07:52:58 【问题描述】:

为什么编译器对doSomething 的前两次调用正常,但使用列表中的两个元素会导致调用不明确?

#include <vector>
#include <string>

void doSomething(const std::vector<std::string>& data) 

void doSomething(const std::vector<int>& data) 

int main(int argc, char *argv[])

    doSomething("hello"); // OK
    doSomething("hello", "stack", "overflow"); // OK
    doSomething("hello", "stack"); // C2668 'doSomething': ambiguous call

    return 0;

【问题讨论】:

【参考方案1】:

单参数和三参数列表都只能匹配std::vector&lt;std::string&gt;std::initializer_list 构造函数。但是,两个参数列表匹配来自std::vector&lt;int&gt; 的构造函数之一:

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

实际上,char const * 可以递增,也可以取消引用以获得可隐式转换为 intchar

【讨论】:

【参考方案2】:

这里发生的是,在两个元素初始化器列表中,两个字符串文字都可以隐式转换为const char*,因为它们的类型是const char[N]。现在std::vector 有一个构造函数,它接受两个指针符合条件的迭代器。因为std::vector&lt;std::string&gt;initializer_list构造函数与std::vector&lt;int&gt;的迭代器范围构造函数冲突。

如果我们将代码改为

doSomething("hello"s, "stack"s);

那么初始化列表的元素现在是std::strings,所以没有歧义。

【讨论】:

doSomething(std::vector&lt;std::string&gt;("hello", "stack"));,但您的解决方案更具可读性。无论如何,如果这是在真实代码中,我可能还会添加一个小注释来解释看似无用的显式性。 我认为如果可能的话,总是调用 initializer_list 构造函数,例如在 std::vector5,1 中,一个向量得到一个元素为 5 和 1 而不是 5 乘以 1 的向量。为什么这里不是这样吗? @ab.o2c 首选初始化列表构造函数,但在这种情况下我们没有std::vector&lt;int&gt;5,1。我们拥有的是std::vector&lt;int&gt;const char*, const char*。由于初始化列表必须与向量的元素具有相同的类型,因此在这种情况下将被忽略并选择迭代器构造函数。 @NathanOliver 你是对的,我的答案是错误的。我以为你说过,两个向量的迭代器构造函数是冲突的,但这不是你的答案 :-) 我需要一些测试才能得到这一点。现在为您 +1。 喜欢使用string operator " " s的解决方案【参考方案3】:

"hello""stack" 都衰减为满足InputIterator 概念的const char *。这允许它们匹配std::vector's constructor #4。

如果您传递 std::string 对象,歧义就会得到解决。

【讨论】:

【参考方案4】:

也许你可以用 initializer_list 参数重载 doSomething(),像这样:

void doSomething(initializer_list<string> l) 
    doSomething(vector<string>(l));

然后,doSomething("hello", "stack"); 将调用您想要的函数。

【讨论】:

“我不确定这是否有效” - 请仅在您知道它们有效的情况下提供答案。其他答案解释了问题发生的原因,因此传达了更多信息,将解决方案留给用户来确定最佳行动方案。 感谢提醒,我在linux/clang++/c++11中测试过,运行良好。

以上是关于为啥初始化列表中的元素数量会导致模棱两可的调用错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在所有边缘上固定 UIStackView 会导致模棱两可的约束错误?

为啥这个方法调用不明确?

尝试初始化 CoreML 模型会导致模棱两可的错误消息

python 为啥我修改列表一个元素会导致所有元素都被修改

为啥这些重载的函数调用模棱两可?

在 PHP 中,为啥我的 scandir 调用会返回错误数量的文件?