为什么 std::vector CTAD 同时接受 int 和 double ?

Too*_*sie 24 c++ c++17 ctad

#include <boost/type_index.hpp>
#include <iostream>
#include <vector>

int main()
{
    std::vector v{2, 3.14};
    std::cout << boost::typeindex::type_id_with_cvr<decltype(v)>().pretty_name() << '\n';

    std::cout << "size: " << v.size() << '\n';
    for (auto x : v)
        std::cout << "- " << x << '\n';
}
Run Code Online (Sandbox Code Playgroud)

输出是:

#include <boost/type_index.hpp>
#include <iostream>
#include <vector>

int main()
{
    std::vector v{2, 3.14};
    std::cout << boost::typeindex::type_id_with_cvr<decltype(v)>().pretty_name() << '\n';

    std::cout << "size: " << v.size() << '\n';
    for (auto x : v)
        std::cout << "- " << x << '\n';
}
Run Code Online (Sandbox Code Playgroud)

std::vector实例化使用自动类型推导(CTAD)。

显然,initializer_list构造函数已被使用(检查),但为什么它同时接受 anint和 adouble并且仍然将类型推导为vector<double>
如果我增加元素数量(同时混合intdouble),编译将失败。

gcc和 的结果相同clang

std::vector<double, std::allocator<double> >
size: 2
- 2
- 3.14
Run Code Online (Sandbox Code Playgroud)

chr*_*ris 23

这里发生了两个重载解析实例。第一个是推导模板参数。由于 init-list 中的两种类型不同,因此此处选择 size+value 构造函数(或更正式地说,从所述构造函数生成的推导指南),将类型推导为double

然后重载解析再次运行以创建对象。现在类型称为double,列表构造函数现在有效,因此可用于初始化对象。

  • @FabiosaysReinstateMonica,我相信使用括号而不是大括号可以做到这一点,因为列表构造函数已完全从图片中删除。 (7认同)
  • 所以你是说两个不同的构造函数用于模板类型推导和初始化。两个操作不应该使用相同的构造函数吗?我无法理解这个问题。 (4认同)
  • @KarenBaghdasaryan,我故意回避这个标准本身,因为不知道我会被困在那里多久,但我可以提供[这个 CppCon 视频](https://youtu.be/-H-ut6j1BYU? t=1955)(在相关幻灯片中)。我想知道当在这两种情况下选择构造函数或其生成的指南时,该提案是否有动机允许不同的结果,或者这个想法是否是将 CTAD 放在顶部,结果只是结果。 (2认同)