Reputation: 3346
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:
constexpr
s.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
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
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
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
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