【问题标题】:C++11: when does compiler consider {} as std::initializer_list, and when doesn't?C++11:编译器何时将 {} 视为 std::initializer_list,何时不考虑?
【发布时间】:2017-09-12 16:04:21
【问题描述】:

我有一个快速示例:

#include <utility>

using namespace std;

struct A{
    int i;
    char c;
};

void f(const A&){}

template<class T>
void g(T&& t)
{
    f(forward<T>(t));
}

int main() {
    A a={1,'@'};//OK
    f({1,'#'});//OK
    g({1,'@'});//Compilation error
    return 0;
}

Clang 会报这个错误:

testArray.cpp:16:5: 错误: 没有匹配函数调用'g' g({1,'@'});//修正:g({1,'@'}) ^ testArray.cpp:9:6:注意:候选模板被忽略:无法推断 模板参数“T” 无效 g(T&& t) ^

我的问题是:

  1. A a={1,'@'};中,如果{}推导出为std::initializer_list,那么如何将std::initilizer_list转换为类型A

  2. f({1,'#'}); 中,当f 需要A 类型时,编译器是隐式生成A 对象,还是从std::initializer_list 转换为A

  3. 为什么,当g()是一个模板时,模板类型推导不起作用给一个类型Astd::forward 是否有助于将消息从f 传达给g,说T 是类型A

【问题讨论】:

  • 这在 C++17 中有所改变,所以当你说“C++11”时,你真的是指 C++11,还是泛指“现代 C++”?跨度>
  • 对于情况 3,这可能有效:g(A{t,'@'}); 因为适当的类型推导应该通过临时发生。
  • @JerryCoffin 请注意 the C++17 changes were considered due to a defect 等在最近的编译器中,他们将它们应用回 C+11 和 C++14。虽然这方面有一段时间不一致。

标签: c++ c++11 templates types initializer-list


【解决方案1】:
  1. 在 'A a={1,'@'}'' 中:如果将 {} 推导出为 std::initializer_list,那么它如何从 std::initilizer_list 转换为类型 A?

不,它与std::initializer_list 无关。 a 只是来自{1,'@'}copy-list-initialized

  1. 在'f({1,'#'});'当 f 需要 A 类型时,编译器是隐式生成 A 对象,还是从 std::initializer_list 转换为 A?

它仍然与std::initializer_list 无关。函数参数是copy-list-initialized from {1,'#'}

  1. 为什么当“g()”是一个模板时,模板类型推导不起作用给一个类型A? “转发”是否有助于将消息从 f 传递到 g,比如说 T 是 A() 类型?

因为这个属于non deduced context,所以模板参数T无法推导导致编译错误。

6) 参数 P,其 A 是一个花括号初始化列表,但 P 不是 std::initializer_list 或对一个的引用:

编译器何时将 {} 视为 std::initializer_list,何时不考虑?

当您将函数参数类型声明为std::initializer_list 并传递一个花括号列表作为参数时,将构造std::initializer_list。另一种情况是auto,例如

auto x1 = {3}; // x1 is deduced as std::initializer_list<int>
auto x2{1, 2}; // after C++17, error: not a single element
               // before C++17, it was std::initializer_list<int>
auto x3{3};    // after C++17, x3 is deduces as int
               // before C++17 it was std::initializer_list<int>

顺便说一句:即使使用auto,它也不适用于{1,'@'},应该是std::initializer_list&lt;char&gt;,还是std::initializer_list&lt;int&gt;

【讨论】:

    猜你喜欢
    • 2022-11-16
    • 2013-01-11
    • 2020-10-13
    • 2021-06-04
    • 1970-01-01
    • 2013-12-07
    • 2014-04-05
    • 2016-11-18
    • 2019-03-18
    相关资源
    最近更新 更多