std :: is_pod vs subclassing

时间:2013-09-20 16:56:46

标签: c++ c++11 pod

有人可以帮我理解为什么以下代码无法编译(g ++ 4.8)。我的理解是可以初始化POD

#include <iostream>
#include <type_traits>

struct my_int
{
  int val_;
};
struct B : public my_int
{
};

int main()
{
  std::cout << std::is_pod<my_int>::value << std::endl;
  std::cout << std::is_pod<B>::value << std::endl;
  const my_int v = { 123 };
  //const B v2 = { 123 }; // does not compile with g++ 4.8.

  return 0;
}

编译是:

g++ -std=c++11 t.cxx
t.cxx: In function 'int main()':
t.cxx:24:21: error: could not convert '{123}' from '<brace-enclosed initializer list>' to 'const B'
   const B v = { 123 };
                     ^

编辑:

感谢大家的回答,我现在理解了聚合初始化的概念。我错过了聚合不能拥有基类的事实。因此,我目前的实施计划需要改变。我想做类似的事情:

template < typename T >
struct base_class
{
  int val_;
};
struct MyInt : public base_class<int>
{
  void Func1() {}
};
struct MyDouble : public base_class<double>
{
  void Func2() {}
};

我将重做上面的代码,以避免使用子类引入特殊的成员函数,同时避免代码重复。

1 个答案:

答案 0 :(得分:5)

免责声明

以一粒盐为例,因为这是我对事物的解释。我绝不是专家。 (我对这里的聚合 - 初始化列表关系有一些疑问。)

<强>答案

据我所知,这是不可能的,因为v2的聚合初始化将应用于非聚合类类型B.

从这个answer你可以认为聚合必须没有基类, 这使得B成为非聚合,因此无法通过大括号括起初始化列表进行初始化。

另一方面,std::is_pod可能不会按照您的想法执行,因为POD定义在C ++ 11中已更改。因此,如果可以使用这样的聚合初始值设定项初始化POD类型,则不会给出提示。

<强>加成

我主要在这里讨论聚合初始化,但更通用的术语是list initialization,它的限制性较小。但是,检查我在链接资源中找到的所有情况,也不可能进行列表初始化 因为(遵循资源的初始化列表的效果列表):

  • 初始化列表不为空
  • B不是聚合
  • B不是std::initializer_list
  • 的专精
  • B没有
    • 构造函数采用初始化列表
    • 构造函数拟合列表的签名
  • B不是参考类型
  • B无法从123进行复制初始化而不是直接初始化,因为没有构造函数采用int
  • B未初始化,因为初始化列表不为空