Showing posts with label cpp11_pod. Show all posts
Showing posts with label cpp11_pod. Show all posts

Nov 3, 2014

[C++11/14] POD type reference

Reference:
What are Aggregates and PODs and how/why are they special?
[C++ / C][NOTE] The Lost Art of C Structure Packing by Eric S. Raymond

Aggregates: (least set)
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1),
no brace-or-equal-initializers for non-static data members (9.2),
no private or protected non-static data members (Clause 11),
no base classes (Clause 10),
and no virtual functions (10.3).



POD:
A POD struct is a non-union class that is both a trivial class and a standard-layout class,
and has no non-static data members of type non-POD struct,
non-POD union (or array of such types).

Similarly, a POD union is a union that is both a trivial class and a standard layout class,
and has no non-static data members of type non-POD struct,
non-POD union (or array of such types).

A POD class is a class that is either a POD struct or a POD union.


Trivial class:
A trivially copyable class is a class that:

— has no non-trivial copy constructors (12.8),

— has no non-trivial move constructors (12.8),

— has no non-trivial copy assignment operators (13.5.3, 12.8),

— has no non-trivial move assignment operators (13.5.3, 12.8), and

— has a trivial destructor (12.4).

A trivial class is a class that has a trivial default constructor (12.1) and is trivially copyable.

[ Note: In particular, a trivially copyable or trivial class does not have virtual functions or virtual base classes.—end note ]

Non-trivial means:
A copy/move constructor for class X is trivial if it is not user-provided and if

— class X has no virtual functions (10.3) and no virtual base classes (10.1), and

— the constructor selected to copy/move each direct base class subobject is trivial, and

— for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial;

otherwise the copy/move constructor is non-trivial.


Standard-layout:
A standard-layout class is a class that:

— has no non-static data members of type non-standard-layout class (or array of such types) or reference,

— has no virtual functions (10.3) and no virtual base classes (10.1),

— has the same access control (Clause 11) for all non-static data members,

— has no non-standard-layout base classes,

— either has no non-static data members in the most derived class and at most one base class with non-static data members,
or has no base classes with non-static data members, and

— has no base classes of the same type as the first non-static data member.

A standard-layout struct is a standard-layout class defined with the class-key struct or the class-key class.

A standard-layout union is a standard-layout class defined with the class-key union.

[ Note: Standard-layout classes are useful for communicating with code written in other programming languages. Their layout is specified in 9.2.—end note ]


---------------
API:
template <typename T> struct std::is_pod;
template <typename T> struct std::is_trivial;
template <typename T> struct std::is_trivially_copyable;
template <typename T> struct std::is_standard_layout;

----------------
Uniform and Value-initialization
Below compiles in C++14, not C++11
struct B
{
  int b_ {1};
};
B b{2};

Jul 24, 2014

[C++11] user-provided definition vs. default

How is “=default” different from “{}” for default constructor and destructor?



From §8.5 [dcl.init]/7:
    If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
      Using = default does not result in a user-provided default constructor, as can be seen in §8.4.2 [dcl.fct.def.default]/4:
        A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
          The member is default-initialized per §12.6.2 [class.base.init]/8:
            In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then
              — if the entity is a non-static data member that has a brace-or-equal-initializer , the entity is initialized as specified in 8.5;
                — otherwise, if the entity is an anonymous union or a variant member (9.5), no initialization is performed;
                  — otherwise, the entity is default-initialized (8.5).

                  Jun 24, 2014

                  [c++] Scalar type

                  Reference: What is a scalar Object in C++?


                  Types in C++ are:


                  • Object types: 
                    • scalars
                      • arithmetic (integral, float)
                      • pointers: T * for any type T
                      • enum
                      • pointer-to-member
                      • nullptr_t
                    • arrays
                      • T[] or T[N] for any complete, non-reference type T
                    • classes (class Foo or struct Bar)
                      • Trivial classes 
                      • Aggregates 
                      • POD classes 
                      • (etc. etc.)
                    • unions
                      • union Zip
                  • Reference types
                    • T &, T && for any object or free-function type T
                  • Function types
                    • Free functions: R foo(Arg1, Arg2, ...)
                    • Member functions: R T::foo(Arg1, Arg2, ...)
                  • (Member types) [see below]
                  • void

                  Apr 26, 2014

                  [C++] struct / class not only different in access level, but in size through inheritance , because of POD

                  Output of the following code:
                  4,4,6  2,2,2

                  POD or non-POD affect the layout size.
                   
                  #include <iostream>
                  
                  struct S {
                     short a;
                     char b;
                  };
                  
                  struct ES : S {
                     char c;
                  };
                  
                  class C {
                     short a;
                     char b;
                  };
                  
                  class EC : C {
                     char c;
                  };
                  
                  
                  
                  int main() {
                     std::cout << sizeof(C) << std::endl;
                     std::cout << sizeof(EC) << std::endl;
                     std::cout << sizeof(ES) << std::endl;
                     std::cout << "alignof(C) " << alignof(C) << std::endl;
                     std::cout << "alignof(EC) " << alignof(EC) << std::endl;
                     std::cout << "alignof(ES) " << alignof(ES) << std::endl;
                  
                  
                     return 0;
                  }
                  
                  Reference:
                  The Lost Art of C Structure Packing by Eric S. Raymond
                  Access specifiers (public/private/protected) don't affect inherited "object size" in anyway.?? not quite

                  Mar 9, 2014

                  [C++11] POD type

                  POD Type
                  Answer from stackoverflow

                  An aggregate is an

                  • array 
                  • class [i.e classes, structs, and unions] (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
                  i.e:
                  • Can have trivial constructor (not defined by user)
                  • No private or protected non-static data members.
                    • Can have member function
                    • Can hava static member function
                  • An aggregate class can have a user-declared/user-defined copy-assignment operator and/or destructor
                  • An array is an aggregate even if it is an array of non-aggregate class type.
                  Type array_name[n] = {a1, a2, ..., am};
                  
                  if(m == n)
                  //the ith element of the array is initialized with ai
                  else if(m < n)
                  //the first m elements of the array are initialized with 
                  //a1, a2, ..., am and the other n - m elements are,
                  //if possible, value-initialized (see below for the explanation of the term)
                  else if(m > n)
                  //the compiler will issue an error
                  else //(this is the case when n isn't specified at all like int a[] = {1,2,3};)
                  //the size of the array (n) is assumed to be equal to m, so 
                  int a[] = {1,2,3} 
                  //is equivalent to int a[3] = {1,2,3};
                  
                  class A
                  {
                  public:
                    A(int){} //no default constructor
                  };
                  class B
                  {
                  public:
                    B() {} //default constructor available
                  };
                  int main()
                  {
                    A a1[3] = {A(2), A(1), A(14)}; //OK n == m
                    A a2[3] = {A(2)}; //ERROR A has no default constructor. Unable to value-initialize a2[1] and a2[2]
                    B b1[3] = {B()}; //OK b1[1] and b1[2] are value initialized, in this case with the default-ctor
                    int Array1[1000] = {0}; //All elements are initialized with 0;
                    int Array2[1000] = {1}; //Attention: only the first element is 1, the rest are 0;
                    bool Array3[1000] = {}; //the braces can be empty too. All elements initialized with false
                    int Array4[1000]; //no initializer. This is different from an empty {} initializer in that
                    //the elements in this case are not value-initialized, but have indeterminate values 
                    //(unless, of course, Array4 is a global array)
                    int array[2] = {1,2,3,4}; //ERROR, too many initializers
                  }
                  


                  A POD-struct is

                  • aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference
                  • has no user-defined copy assignment operator 
                  • no user-defined destructor. 
                  • Similarly, a POD-union is 
                    • an aggregate union that has no non-static data members of type non-POD-truct, non-POD-union (or array of such types) or reference
                    • has no user-defined copy assignment operator 
                    • no user-defined destructor. 
                  • A POD class is a class that is either a POD-struct or a POD-union.
                  struct POD
                  {
                    int x;
                    char y;
                    void f() {} //no harm if there's a function
                    static std::vector<char> v; //static members do not matter
                  };
                  
                  struct AggregateButNotPOD1
                  {
                    int x;
                    ~AggregateButNotPOD1(){} //user-defined destructor
                  };
                  
                  struct AggregateButNotPOD2
                  {
                    AggregateButNotPOD1 arrOfNonPod[3]; //array of non-POD class
                  };
                  


                  POD-classes, POD-unions, scalar types, and arrays of such types are collectively called POD-types.

                  • POD-classes are the closest to C structs. 
                  • Unlike C struct, POD's can have member functions and arbitrary static members, but neither of these two change the memory layout of the object. 
                  • If want to write a more or less portable dynamic library that can be used from C and even .NET, should try to make all exported functions take and return only parameters of POD-types.
                  • The lifetime of POD object begins when storage for the object is occupied and finishes when that storage is released or reused.
                  • For objects of POD types it is guaranteed by the standard that when you memcpy the contents of object into an array of char or unsigned char, and then memcpy the contents back into object, the object will hold its original value. 
                  • Do note that there is no such guarantee for objects of non-POD types. 
                  • Also, we can safely copy POD objects with memcpy.
                  #define N sizeof(T)
                  char buf[N];
                  T obj; // obj initialized to its original value
                  memcpy(buf, &obj, N); // between these two calls to memcpy,
                  // obj might be modified
                  memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
                  // holds its original value
                  


                  goto statement:

                  • Illegal (the compiler should issue an error) to make a jump via goto from a point where some NON-POD variable was not yet in scope to a point where it is already in scope.
                  //ill form
                  int f() {
                    struct NonPOD { NonPOD(){}};
                    goto label;
                    NonPOD x;
                  label:
                    return 0;
                  }
                  
                  // OK
                  int g(){
                    struct POD {int i;  char c;};
                    goto label;
                    POD x;
                  label:
                    return 0;
                  }
                  

                  Why can't variables be declared in a switch statement?

                  Guaranteed that there will be no padding in the beginning of a POD object.
                  In other words, if a POD-class A's first member is of type T,
                  we can safely reinterpret_cast from A* to T* and get the pointer to the first member and vice versa.


                  switch (i)
                  {
                     case 0:
                       int j; // 'j' has indeterminate value
                       j = 0; // 'j' initialized to 0, but this statement
                              // is jumped when 'i == 1'
                       break;
                     case 1:
                       ++j;   // 'j' is in scope here - but it has an indeterminate value
                       break;
                  }