leewz
leewz

Reputation: 3346

Why does having a base class disqualify a class from being aggregate?

What is it about having an aggregate public base class (or even multiple aggregate public base classes) that would make a class lose the nice properties of aggregate classes?

Definition of "aggregate base class" from http://en.cppreference.com/w/cpp/language/aggregate_initialization http://en.wikipedia.org/wiki/C++_classes#Aggregate_classes


The nice properties of aggregate classes:

Abridged example of initialization from http://en.cppreference.com/w/cpp/language/aggregate_initialization#Example:

#include <string>
#include <array>
struct S {
  int x;
  struct Foo {
    int i;
    int j;
    int a[3];
  } b;
};

int main()
{
  S s1 = { 1, { 2, 3, {4, 5, 6} } };
  S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision
}

See also: What are Aggregates and PODs and how/why are they special?

Upvotes: 16

Views: 3648

Answers (4)

Kaznov
Kaznov

Reputation: 1163

Since C++17 classes that have public, non-virtual base classes can be aggregates.

struct Base1 {
 int a, b;
};
struct Base2 {
 int c;
};

struct Foo : Base1, Base2 {
    int d, e;
};

Objects of struct Foo can be aggregate-initialized. The following initializations are equivalent:

Foo foo {Base1{1, 2}, Base2{3}, 4, 5};
Foo foo {{1, 2}, {3}, 4, 5};
Foo foo {1, 2, 3, 4, 5};

Upvotes: 6

leewz
leewz

Reputation: 3346

According to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3308.pdf

Despite the clear intentions of the standard, type B is not a literal type:

struct A {}; struct B : A {};

This is because its constructor is not implicitly defined until it is odr-used, and until that point it has no constexpr constructors.

Honestly not sure what this means, though.

Upvotes: 4

aaronman
aaronman

Reputation: 18751

This is the definition of an aggregate from the c++11 standard, that is really all I can give without trying to guess what the committee was thinking when they made this decision.

1 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).

In the bold it says that an aggregate has no base classes.

As for the issue with inheritance that the other answer brings up you can make uniform initialization work with inheritance. NOTE: A is still an aggregate.

struct A {                                                                         
    int val_A;                                                                                                                        
};                                                                                 

struct B : public A {                                                              
    int val_B;                                                                     
    B(int a, int b) : A{a}, val_B(b) {}                                            
};                                                                                 
int main() {                                                                       
    B b {2,3};                                                                     
    return 0;                                                                      
}  

You just have give B a constructor, IMO the standard could have just as easily chosen this as the default. Aggregates were probably kept in because they were in previous standards but the truth is with c++11 features you really don't even need them. In fact one issue is that std::array needs double braces since it has no initializer list constructor, I think this issue is solve in c++14.

I would like to add that I don't see how much being an aggregate adds to a class given the new features of uniform initialization and initializer lists.

Upvotes: 3

user3458
user3458

Reputation:

How would you initialize the base class?

Derived d = {{1, 2}, 3, 4};

Or

Derived d = {1, 2, 3, 4};

Is

Derived d = {3, 4};

permitted?

To avoid all of this, no base classes.

Upvotes: 2

Related Questions