大括号初始化继承的pod

nam*_*ame 11 c++ pod c++11

#include <iostream>
#include <type_traits>


struct base_pod_t {
    unsigned x;
};

struct der_pod_t : public base_pod_t { };

int main()
{
    std::cout << "base_pod_t is POD: " << std::is_pod<base_pod_t>::value << std::endl;
    std::cout << "der_pod_t  is POD: " << std::is_pod<der_pod_t>::value << std::endl;
    base_pod_t b1 = {};     // OK
    base_pod_t b2 = {3};    // OK

    der_pod_t p1 = {};      // OK
//    der_pod_t p2 = {4};   // ERROR!
}
Run Code Online (Sandbox Code Playgroud)

最后一行导致错误.如何der_pod_t用值来初始化?


似乎即使它是一个POD它试图使用构造函数?


编辑: 由于@Praetorian和@dyb建议它是POD因此结果std::is_pod<der_pod_t>::value是正确的.

Pra*_*ian 16

base_pod_t 是一个聚合,您正在执行的初始化是聚合初始化.

来自§8.5.1[dcl.init.aggr]

1一种骨料为数组或一个类(第9节)没有用户提供的构造(12.1),无私有或保护非静态数据成员(第11),没有基类(第10节),并且没有虚拟功能( 10.3).

2当初始化程序列表初始化聚合时,如8.5.4中所述,初始化程序列表的元素将作为聚合成员的初始化程序,增加下标或成员顺序.每个成员都是从相应的initializer子句复制初始化的....

但是,der_pod_t它不是聚合,因为它有一个基类.这是一个POD,列表初始化的相同规则不适用.现在,当编译器看到一个非空的braced-init-list时,它将首先搜索一个带有initializer_list.的构造函数.如果没有找到它,则尝试匹配该类的其他构造函数.由于der_pod_t没有构造函数将单个int参数作为参数,因此会发生错误.


Dav*_*vid 5

从CPP 17开始,可以稍作改动,在每个基本类的初始化器列表中都需要其他{}。请注意,在下面的示例中,{1,2}如何包含在“ {}”中并初始化i,j,而“ 3”则初始化派生的k。

struct base_pod
{
    int i, j;

};

struct der_pod : public base_pod
{
    int k;
};

der_pod dp{ {1 , 2}, 3 };
Run Code Online (Sandbox Code Playgroud)

这适用于GCC版本7.3.0(不确定较早的版本),但在VS17(v 15.9.4)和带有“ / std:c ++ 17”标志的VS17上失败,因此请注意编译器的支持/标志。

相关的变更建议在这里