为什么调用不明确的 ctor 时没有编译时错误?
Why is no compile-time error when calling an ambiguous ctor?
#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;
}
代码输出:
8
1
我知道这是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
构造函数。
您链接到的问题不是关于初始化向量的歧义。歧义在于选择函数重载。两者都是可行的,因为两者都接受不同的向量,该向量本身可以从同一个初始值设定项列表中明确初始化。
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 如何在常量计算表达式中获取编译时错误?
- C++根据调用的构造函数强制编译时错误
- 使用 std::iterator_traits<> 时编译时错误不明确
- is_same和variadic模板编译时错误无效转换
- 私有运营商删除会触发 GCC 和 Clang 的编译时错误,但不会在 MSVC 上触发编译时错误
- 运行时与编译时多态性:更好的可读性与编译时错误检查,更重要的是
- 引发编译时错误
- 为什么调用不明确的 ctor 时没有编译时错误?
- 在 sizeof 运算符上强制编译时错误
- 未经授权的私有类成员访问会产生编译时错误而不是运行时错误?
- 从Mac上的终端编译时C 错误
- 使用MINGW-W64使用-M32选项(32位代码)编译时错误
- C++线程错误 - 带有类参数的编译时错误
- 如果编译时间构量参数是错误的,则生成编译时错误
- 尝试调用指向成员函数的函数指针时出现编译时错误
- 编译时错误:删除了联合默认构造函数
- 初始化启动对象时出现编译时错误
- 如果在C++中将成员添加到类中,则会导致编译时错误的技术
- 如何设计可序列化类以使任何非序列化属性都会导致编译时错误