trivial vs. standard layout vs. POD

Layout is how the members of an object of class, struct or a union is arranged in the memory. This may be contigious or not.Quite often the language specifies the layout , but if there are something like virtual function ,virtual base class etc , then the complier is free to choose the layout and that may not be contigiuos. This leads to several issues that we cannot serialize the object suitably or pass to programs written in other languages like C or functions like memcopy because we cannot copy the data reliably that it is not in contigious locations.

Inorder to enable the compilers and c++ programs to support the above mentioned operations c++ has introduced 3 categories for the simple structures and classes.

Trivial

A class or struct is trivial if it follows the rules:

  • no virtual function or virtual base class
  • no user-defined constructor/operator/destructor
  • base class should be trivial
  • all the class members should be trivial

If a class is trivial then its layout is contigious but there may be padding accordingly and the compiler is free to choose the order of the members in the layout. So even though we can memcopy the object it is not reliable if we copy that object to C program.We can have different access specifiers in the same class itself and if use a parameterized constructor obviously we have to specify the default contructor. But if you want to keep the class trivial then you should explicitly make the constructor default.The constructors should be public.

Standard-layout

  • No virtual functions and virtual base class
  • All the non-static members should have same access specifiers
  • All non-static members should be of standard layout
  • All base classes should be of standard layout
  • All the members of the base class should be static
  • The type of the base class and first non-static member of the class should not be the same

Standard layout is well defined and it can be memcopied reliably and passed to C programs suitably. Also standard layout functions can have user-defined special member funtions like constructor and destructor.

POD(Plain old data)

If a class or structure is both trivial and standard layout , then it is said to be POD.Each member is stored in the order as specified when the object is declared. POD classes should have POD non-static data members.POD classes can be copied or passed to C programs reliably.

C++ program with a class which is trivial , standard layout and therefore POD.

#include<iostream>
#include<type_traits>
class xyz
{
public:
    int a;
    int b;
    xyz() = default;
    xyz(int x, int y) :a(x), b(y) {}
};
int main() {
    std::cout << std::is_trivial<xyz>() << std::endl;//true
    std::cout << std::is_standard_layout<xyz>() << std::endl;//true
    std::cout << std::is_pod<xyz>() << std::endl;//true
}

Literal types

For a literal type the layout can be determined at the time of compilation .Examples of literal types are void,scalar types such as int , float etc,references,Arrays of void, scalar types or references and A class that has a trivial destructor, and one or more constexpr constructors that are not move or copy constructors. Additionally, all its non-static data members and base classes must be literal types and not volatile


I don't think it can be done in truly layman's terms, at least without a lot of extra explanation. One important point is static vs. dynamic initialization, but explaining that to a layman would be several pages in itself...

PODs were (mis-)defined in C++98. There are really two separate intents involved, neither expressed very well: 1) that if you compile a C struct declaration in C++, what you get should be equivalent to what you had in C. 2) A POD will only ever need/use static (not dynamic) initialization.

C++0x/11 drops the "POD" designation (almost) entirely, in favor of "trivial" and "standard layout". Standard layout is intended to capture the first intent -- creating something with a layout the same as you'd get in C. Trivial is intended to capture the support for static initialization.

Since new T vs. new T() deals with initialization, you probably want is_trivial.

I'm not sure about compiler magic being required. My immediate reaction would be probably yes, but knowing some of the things people have done with TMP, I have a hard time being certain somebody couldn't do this too...

Edit: for examples, perhaps it's best to just quote the examples from N3290:

struct N { // neither trivial nor standard-layout
   int i;
   int j;
    virtual ~N();
};

struct T { // trivial but not standard-layout
    int i;
private:
    int j;
};

struct SL { // standard-layout but not trivial
    int i;
    int j;
    ~SL();
};

struct POD { // both trivial and standard-layout
    int i;
    int j;
};

As you can undoubtedly guess, POD is also a POD struct.


For POD types new T() is value-initialization(will value-initialize all members) ,and new T will not initialize the members (default-initialization). For differences between different forms of initialization see this question. Bottom line: you need is_pod.

Tags:

C++

Typetraits