#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参数作为参数,因此会发生错误.
从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上失败,因此请注意编译器的支持/标志。