c++ - std::initializer_list,大括号初始化和 header

标签 c++ templates initializer-list

在阅读不同主题时,我遇到了一种奇怪的行为,至少对我来说是这样。 这整个想法源于 auto 之间的特殊互动。和大括号。如果你写这样的东西:

auto A = { 1, 2, 3 }

编译器会推导出 A成为 std::initializer_list .奇怪的是,类似的规则不仅适用于 auto。 ,那里可能有特殊的原因呢,也可能是其他的事情。 如果你写如下:

template<typename T>
void f(std::vector<T> Vector)
{
    // do something
}

你当然不能这样调用它:

f({ 1, 2, 3});

即使 std::vector可以支撑初始化。但是,如果您替换 std::vectorstd::initializer_list ,调用有效,编译器将正确推断 int作为类型T .然而,更有趣的是,在前一种情况下,您需要 #include <vector> , 在后者中你不需要 #include <initializer_list> .这让我思考,经过测试,我以某种方式意识到 std::initializer_list不需要自己的标题,因此它在某种程度上是“基本”功能的一部分。

此外,为了让一切都有意义,std::initializer_list应该以或多或少与 lambda 对可调用对象的方式相同(在最严格的意义上,即带有 operator() 的对象)。换句话说,未命名的大括号定义应该默认为 std::initializer_list就像 lambda 是(大部分)未命名的可调用对象一样。

这个推理正确吗?此外,这种行为是否可以改变?如果可以,如何改变?

更新:initializer_list 的 header 被发现是从 iostream 传递过来的。 (真的很奇怪)。然而,问题仍然存在:为什么调用适用于 std::initializer_list而不是std::vector ?

最佳答案

不包含 initializer_list 是不正确的 (so it requires a diagnostic)如果我们使用 std::initializer_list 则 header .我们可以从 [dcl.init.list]p2 中看到这一点:

... The template std::initializer_list is not predefined; if the header <initializer_list> is not included prior to a use of std::initializer_list — even an implicit use in which the type is not named (9.1.7.4) — the program is ill-formed.

您很可能会传递包含标题,它格式正确但会使您的代码更脆弱,因此请包含您使用的内容。

我们可以从一个实时的godbolt 示例中看到,如果没有包含,我们可以从gcc/clang/MSVC 获得所需的诊断信息。例如:

error: use of undeclared identifier 'std'    
void foo( std::initializer_list<int>) {
          ^

包括<vector><iostream>我们 no longer obtain a diagnostic .

[temp.deduct.type]p5 涵盖了为什么它没有按照您的预期进行推断。这告诉我们这是一个非推断的上下文:

The non-deduced contexts are:
...
- A function parameter for which the associated argument is an initializer list ([dcl.init.list]) but the parameter does not have a type for which deduction from an initializer list is specified ([temp.deduct.call]).> [ Example:

template<class T> void g(T);
g({1,2,3});                 // error: no argument deduced for T

— end example  ]
...

另见 [temp.deduct.call]p1 :

... Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context ([temp.deduct.type]) ...

关于c++ - std::initializer_list,大括号初始化和 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52924740/

相关文章:

c++ - 为什么在 VS2019 中 std::initializer_list 的初始化似乎失败了

C++ 初始值设定项列表成员仍在调用默认构造函数?

c++ - 流行的 (c++) "error: no matching function for call to ... ",虽然有一个踢

c++ - 我的 SFML 项目的主循环只发生一次。有人知道为什么吗?

c++ - 拍摄第一张网络摄像头照片后,OpenCV 不保存第二张网络摄像头照片

c++ - 这个模板函数是在哪里生成的呢?可以通过 g++ 编译,但不能在 Visual Studio 中编译

c++ - 模板函数使用参数包时如何传递其他模板参数?

c++ - 为什么模板非类型参数不能是类类型

c++ - QML QWidget 容器

c++ - 如何在不使用大量 CPU 的情况下将大量丰富的内容(图像、格式)快速附加到控件?