c 11 – 为什么“矢量v {{5,6}};`工作?我以为只有一双{}被允许?

给定一个具有两个构造函数的类A,取initializer_list< int>和initializer_list< initializer_list< int>>分别
A v{5,6};

打电话给前者,和

A v{{5,6}};

呼吁后者,如预期. (clang3.3,显然gcc的行为有所不同,看到答案,标准要求什么?)

但是如果我删除第二个构造函数,那么A v {{5,6}};仍然编译,它使用第一个构造函数.我没想到这个
我认为A v {5,6}将是访问initializer_list< int>的唯一方法.构造函数.

(我在std :: vector和this question I asked on Reddit播放时发现了这一点,但是我创建了自己的A类,以确保它不仅仅是std :: vector的界面的怪癖.)

解决方法

我想这个 answer might be relevant.

Yes,this behavIoUr is intended,according to §13.3.1.7 Initialization
by list-initialization

When objects of non-aggregate class type T are list-initialized (8.5.4),overload resolution selects the constructor in two phases:

— Initially,the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of
the initializer list as a single argument.

— If no viable initializer-list constructor is found,overload resolution is performed again,where the candidate functions are all
the constructors of the class T and the argument list consists of the
elements of the initializer list.

在gcc我试过你的例子.我得到这个错误

error: call of overloaded 'A(<brace-enclosed initializer list>)' is ambiguous

如果我使用三套大括号,gcc会停止抱怨.即:

#include <iostream>
#include <vector>
#include <initializer_list>

struct A {
    A (std::initializer_list<int> il) { 
        std::cout << "First." << std::endl;
    }
    A (std::initializer_list<std::initializer_list<int>> il) { 
        std::cout << "Second." << std::endl;
    }
};

int main()
{
    A a{0}; // first
    A a{{0}}; // compile error
    A a2{{{0}}}; // second
    A a3{{{{0}}}}; // second
}

试图镜像向量的构造函数,这里是我的结果:

#include <iostream>
#include <vector>
#include <initializer_list>

struct A {
    A (std::initializer_list<int> il) { 
        std::cout << "First." << std::endl;
    }
    explicit A (std::size_t n) {
        std::cout << "Second." << std::endl;
    }
    A (std::size_t n,const int& val) {
        std::cout << "Third." << std::endl;
    }
    A (const A& x) {
        std::cout << "Fourth." << std::endl;
    }
};

int main()
{
    A a{0};
    A a2{{0}};
    A a3{1,2,3,4};
    A a4{{1,4}};
    A a5({1,4});
    A a6(0);
    A a7(0,1);
    A a8{0,1};
}

main.cpp:23:10: warning: braces around scalar initializer

    A a2{{0}};

         ^~~

1 warning generated.

First.
First.
First.
First.
First.
Second.
Third.
First.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...