2
votes

take two following classes:

class Test1{
 public:
  Test1()=default;
  Test1(char in1,char in2):char1(in1),char2(in2){}
  char char1;
  char char2;
};
class Test2{
 public:
  Test2()=default;
  Test2(char in1,char in2):char1(in1),char2(in2){}
 private:
  char char1;
  char char2;
};

I know in c++0x both of these classes are considered as POD types and we can initialize objects of them using initializer lists as below:

Test1 obj1={'a','b'};//valid in c++0x
Test2 obj2={'a','b'};//valid in c++0x

But I wonder what the technical reason is that when we have different access specifiers in a class like below, it's not possible to use initializer list for initializing objects of that class and that class is not considered as a POD type ?

class Test{
 public:
  Test()=default;
  Test(char in1,char in2):char1(in1),char2(in2){}
  char char1;
 private:
  char char2;
};
Test obj={'a','b'};//invalid in c++0x

In case you don't know definition of PODs in c++0x:
A class/struct is considered a POD if it is trivial, standard-layout, and if all of its non-static members are PODs.

A trivial class or struct is defined as one that:

  1. Has a trivial default constructor. This may use the default constructor syntax (SomeConstructor() = default;).
  2. Has a trivial copy constructor, which may use the default syntax.
  3. Has a trivial copy assignment operator, which may use the default syntax.
  4. Has a trivial destructor, which must not be virtual.

A standard-layout class or struct is defined as one that:

  1. Has only non-static data members that are of standard-layout type
  2. Has the same access control (public, private, protected) for all non-static members
  3. Has no virtual functions
  4. Has no virtual base classes
  5. Has only base classes that are of standard-layout type
  6. Has no base classes of the same type as the first defined non-static member
  7. Either has no base classes with non-static members, or has no non-static data members in the most derived class and at most one base class with non-static members. In essence, there may be only one class in this class's hierarchy that has non-static members.

In case you don't know what a trivial constructor or operator is:
Compiler generates a trivial one of each of following items for a class, in case it isn't user-declared: Copy constructor, destructor and copy assignment operator.
And also if there's no user-declared constructor for a class, a trivial default constructor is generated for that class, in case there are any user-declared constructors you can use the syntax(SomeConstructor() = default;) to make your own trivial default constructor.

2
None of the classes in the question are POD, even by the C++0x definition of POD. In C++0x, a POD class type must be trivial, meaning it has a trivial default constructor. Your classes have no default constructor. The first two classes are standard-layout classes, though. - James McNellis
the first two classes are PODs, read additional info I added. - Pooria
@Pooria: All three of your classes have a user-declared constructor, therefore there is no implicitly declared default constructor. - James McNellis
@Pooria: Wrong. If there is any user-declared constructor, then no default constructor is implicitly declared. Your classes all have a user declared constructor. Ergo, none of your classes have an implicitly declared default constructor. - James McNellis
@Pooria: N3092 §12.1.5: "If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted." You can declare the trivial default constructor using the ` = default;` syntax, but you have not done that for any of these classes. - James McNellis

2 Answers

3
votes

The "technical" reason is due to the following:

Nonstatic data members of a (non-union) class with the same access control are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (C++0x §9.2/12).

So long as all the nonstatic data members have the same access control, their order is well-specified; otherwise their order is unspecified.

0
votes
class Test{
 public:
  Test()=default;
  Test(char in1,char in2):char1(in1),char2(in2){}
  char char1;
 private:
  char char2;
};

considering above class following syntax is valid in c++0x:

Test obj={'a','b'};//valid in c++0x

The final proposal is here.