1

最近我意识到,在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; 
} 

下面compiles fine的示例代码我深知统一初始化的,就像使用{ }声明对象,但不知道我们还可以调用构造函数。我们不能通话功能,虽然,以下doesn't compile

#include <initializer_list> 

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

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

因此,要总结,我的问题是:被委托的构造函数,允许调用只用花括号中的初始列表构造函数时有特殊规则,像Foo{something}

+0

你问最有趣的问题 – AndyG

回答

5

是的,一个MEM-初始化Foo{42}可以包含一个括号的表达式列表支撑-INIT列表。无论mem-initializer-id表示构造函数的类,基类还是成员:无论是构造函数委托还是构造函数都不成立时,都是如此。请参见[class.base.init]中的语法。

此外,该标准规定([class.base.init]在C++ 14/7),其由所述表达式列表支撑-INIT列表初始化根据通常的规则发生初始化。因此,如果初始化程序是一个支持初始化列表那么std::initializer_list构造函数将在重载分辨率中受到青睐。

2

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

如果该类自己的名字出现在类或标识符 成员初始值设定项列表,则该列表必须只包含该成员初始值设定项的一个成员 ;这样的构造是被称为委托 构造,并且由 初始化列表的唯一成员所选择的构造是在目标的构造在这种情况下,目标 构造由重载解析选择并执行第一, 则控制返回到委托构造函数,其执行体 。

因此,通过重载解析,您可以调用您的初始化程序列表构造函数,就像在“普通”代码中调用它一样,因为。

但是,我不知道任何应该允许调用一个函数来接受一个初始化列表,就像你可以调用一个构造函数一样。

编辑:More约构造规则(重点再次矿):

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

1)初始化使用 直接初始化,或者,如果表达式列表是空的, 值初始化由类或标识符命名基部或构件
2)初始化由 命名的基类或成员class-or-使用列表初始化(成为 值初始化,如果该列表为空并初始化一个聚合时聚合初始化 )
3)初始化使用 包膨胀

所以根据#多个碱基标识符2,它看起来是合法的。

+0

我明白这一点,我知道我可以委托给一个init-list,但不知道我也可以称它为'Foo {...}'而不一定是'Foo ({...})'。 – vsoftco