调用构造函数,而不是大括号括号(Calling constructor with braces in

2019-10-22 18:32发布

最近,我意识到,在C ++ 11我们可以称之为一个委托初始化列表构造状

Foo() : Foo{42} // delegate to Foo(initializer_list<>)

这是语法正确吗? 这似乎是,虽然我本来期望调用函数时,总是使用括号,如Foo({42}) 下面的示例代码编译罚款在两个铛++和g ++

#include <iostream>
#include <initializer_list>

struct Foo
{
    Foo() : Foo{42} // I would have expected invalid syntax, use Foo({42})
    {
        std::cout << "Foo()... delegating constructor\n";
    }
    Foo(std::initializer_list<int>)
    {
        std::cout << "Foo(initializer_list)\n";
    }
};

int main()
{
    Foo foo;
}

我深知统一初始化的,喜欢用声明的对象 { }但不知道我们还可以调用构造函数。 我们不能调用函数虽然,以下不会编译 :

#include <initializer_list>

void f(std::initializer_list<int>){}

int main()
{
    f{5}; // compile time error, must use f({5})
}

因此,要总结,我的问题是:是否有特殊规定委托构造函数,允许在仅使用大括号,就像调用初始化列表构造Foo{something}

Answer 1:

是的,MEM-初始化诸如Foo{42}可以包含一个括号表达式列表或一个支撑-INIT-列表 。 这是无论MEM-初始化-ID是否表示构造函数的类,基类或成员的情况:即,当两者构造代表和当它没有。 参见[class.base.init]语法。

此外,该标准规定([class.base.init] / 7在C ++ 14),其由表达式列表支撑-INIT-list中的初始化根据初始化的通常的规则进行。 因此,如果初始化是一个支撑,初始化列表 ,然后std::initializer_list的构造将在重载的青睐。



Answer 2:

我认为规则是很清楚,你将被允许委托给一个初始化列表构造(重点煤矿):

如果类本身的名称显示为部件初始化列表类或标识符,则列表必须仅包含一个成员初始化的; 这样的构造是被称为委托构造,并且通过初始化列表的唯一成员所选择的构造是在目标的构造在这种情况下, 目标的构造方法由重载解析选择并执行第一,则控制返回到委派构造和它的身体被执行。

因此,通过重载,你可以打电话给你的初始化列表构造就好像你在,因为“正常”的代码调用它。

但是,我不知道什么是应该允许调用接受的,你可以调用构造函数具有一个相同的方法,初始化列表的功能。

编辑: 更多关于构造规则(再次强调我的):

任何构造的函数定义的主体中,该复合语句的开括号之前,可包括构件初始化列表,其语法是冒号:,随后一个或多个成员,初始化器,每个的逗号分隔的列表其具有下面的语法
类或标识符(表达式列表(可选))(1)
类或标识符支架-INIT列表(2)(由于C ++ 11)
参数包...(3)(因为C ++ 11)

1)初始化使用直接初始化或由类或标识符命名基部或构件,如果表达式列表是空的,值初始化
2) 初始化用列表初始化(初始化的聚集体时成为值初始化,如果该列表为空和骨料初始化)由类或标识符命名基部或构件
3)初始化用包膨胀多个碱基

因此,根据#2,似乎它是合法的。



文章来源: Calling constructor with braces instead parantheses