embrace POD type util they die

C++03的POD type,在C++11后由三个type_traits替代,standard layout, trivial, trivial copyable。 standard layout关注数据成员布局,而trivial关注行为。 我们首先看standard layout,

class Date{
    int day;
    int mouth;
    public:
    Date(){}
};

struct MyDate{
    int d;
    int m;

};
union DateMyDate{
    Date date;
    MyDate mydate;
};

int getMonth(const Date & d)
{
    return DateMyDate(d).mydate.m;
}

int getday(Date* d)
{
    return *reinterpret_cast<int*>(d);
}

这里Date和MyDate类型都是standard layout,但Date的成员都是私有的,MyDate的成员是共有的。我们可以通过创建union DateMyDate,访问他们的common initial sequence的成员任意成员。如getMonth访问第二个。对于第一个成员,可简便的用reinterpret_cast访问就可。

接着我们看trivial

class First{
    public:
//  ~First(){}

};
class Second{
    public:
 //   Second(){}
    int i;
};
union FS{
 First f;
 Second s;
};
 constexpr void foo()
{
    FS u;
    u.s.i=1; //assign line
}

对于union ,上述的assign line, 要被赋值给非active member的字段,如果active member f的析构是trivial的,而非active member s的构造函数是trivial的,那么将赋值成功并立刻将active member转换为s;如果约束不满足,将是UB,反注释掉First的析构或Second的构造将编译失败。

最后我们看看trivial copyable,这里指对象可以使用memmove memcopy来操作。对于trivail copyable,要求所有eligible的copy, copy assign,move,move assign以及析构必须是trivial的,且eligible析构不能被delete,注意这里没有对这些函数是否public protected or private的要求,

class A{
    private:
    A(const A&)=delete;
    A& operator=(const A&)=delete;
    A(A&&)=delete;
    A& operator=(A&&)=delete;
    ~A()=default;
};
static_assert(std::is_trivially_copyable_v<A>);

这里的A是满足trivial copyable要求的。

Posted 2022-06-11