C++11:编译器何时将 {} 视为 std::initializer_list,何时不视为?

C++11: when does compiler consider {} as std::initializer_list, and when doesn't?

我有一个快速示例:

#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: error: no matching function for call to 'g'
        g({1,'@'});//fix: g<A>({1,'@'})
        ^
    testArray.cpp:9:6: note: candidate template ignored: couldn't infer
          template argument 'T'
    void g(T&& t)
         ^

我的问题是:

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

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

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

  1. In 'A a={1,'@'}'' :If {} is deduced as std::initializer_list, then how it's converted from std::initilizer_list to type A?

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

  1. In 'f({1,'#'});' When f requires a type A, does compiler implicitly generates an A object, or it converts from std::initializer_list to A?

还是和std::initializer_list没有关系。函数参数是copy-list-initialized from {1,'#'}.

  1. why when "g()" is a template, the template type deduction doesn't work to give a type A? Does "forward" help to convey the message from f to g, say that T is type A()?

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

6) The parameter P, whose A is a braced-init-list, but P is not std::initializer_list or a reference to one:

when does compiler consider {} as std::initializer_list, and when doesn't?

当您将函数参数类型声明为 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<char> 还是 std::initializer_list<int>