xml*_*lmx 5 c++ initializer-list ambiguous overload-resolution c++11
#include <iostream>
#include <vector>
int main()
{
auto v1 = std::vector<std::size_t>(std::size_t{8});
std::cout << v1.size() << std::endl;
auto v2 = std::vector<std::size_t>{std::size_t{8}};
std::cout << v2.size() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
代码输出:
8
1
Run Code Online (Sandbox Code Playgroud)
我知道这是C ++中的一个众所周知的问题,因为:
std::vector<std::size_t>(std::size_t{8}) 来电
explicit vector(size_type count) 而
std::vector<std::size_t>{std::size_t{8}} 来电
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator())。
出乎我的意料:
为什么第二次调用不触发针对重载解析度歧义的编译时错误?
在另一个相关问题中,一段类似的代码确实触发了歧义错误。
因为没有歧义会导致错误。当我们使用列表初始化时,重载分辨率明显不同。它分两个阶段有意完成。
[over.match.list]
1当非聚合类类型T的对象被列表初始化([dcl.init.list])时,重载解析会分两个阶段选择构造函数:
最初,候选函数是类T的初始化器列表构造函数([dcl.init.list]),参数列表由作为单个参数的初始化器列表组成。
如果找不到可行的初始化器列表构造函数,则再次执行重载解析,其中候选函数是T类的所有构造器,并且参数列表由初始化器列表的元素组成。
如果初始化列表中没有元素,并且T具有默认构造函数,则省略第一阶段。在复制列表初始化中,如果选择了显式构造函数,则初始化的格式不正确。[注意:这与其他情况([over.match.ctor],[over.match.copy])不同,在其他情况下,复制转换只考虑转换构造函数。仅当此初始化是重载解决方案最终结果的一部分时,此限制才适用。—尾注]
第一步,仅 std::initializer_list考虑构造函数。我们可以进入第二步,仅在第一个重载解析失败时才考虑其他构造函数。显然,重载解析不会失败找到合适的std::initializer_list构造函数。
您链接到的问题不是关于初始化向量的歧义。模糊性在于选择函数重载。两者都是可行的,因为它们都接受不同的向量,而这些向量本身可以从相同的初始化程序列表中明确初始化。