I am trying to understand what an aggregate class/struct/union is: Here is from the C++ standard:
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).
So I've written this for testing:
struct NonAggregate{
virtual void f()const&{} // virtual member function makes the struct non-aggregate
};
struct Bar{}; // aggregate
struct X{}; // aggregate
struct Foo : Bar, X{
// Foo() = default; // if un-comment out makes Foo non-aggregate
Foo& operator =(Foo const&){return *this;} // ok
~Foo(){} // ok
int x_ = 0; // has an initializer. ? still aggregate?
Bar b_{}; // has an initializer. still aggregate?
private:
static double constexpr pi_ = 3.14;
};
double constexpr Foo::pi_; // definition needed- (although it has an in-class intializer) if Foo::pi_ used outside of the class
int main(){
std::cout << std::boolalpha << "Foo is an aggregate type: " << std::is_aggregate<Foo>::value << '\n';
}
The output is:
Foo is an aggregate type: true
So why If I default the synthesized default constructor Foo
is no more an Aggregate? As long as I've not provided a user-defined one?
Also the standard says: no base classes (Clause 10)
but my struct inherits multiply from two aggregate structs Bar
and X
but still n Aggregate??!
The standard says: no brace-or-equal-initializers for non-static data members (9.2)
but I have initializers for non-static data members x_
and b_
but the compiler still consider Foo
as an aggregate struct?? Thank you!
*P.S: I've used GCC and C++2a standard
The rules for what is and what is not an aggregate has changed a lot over various standard versions. This answer briefly highlights the changes related with OP's three questions. For a more thorough passage, see e.g. The fickle aggregate, which walks through these different rules along with the correct standard (version) references.
So why If I default the synthesized default constructor Foo is no more an Aggregate? As long as I've not provided a user-defined one?
In C++11 through C++17, the requirement reads "no user-provided" constructors, which still allows declaring constructors as long as they are defined as explicitly-defaulted or explicitly-deleted on their first declaration.
// Aggregate in C++11 through C++17. Not an aggregate in C++20.
struct A {
A() = default; // user-declared, but not user-provided
};
// Aggregate in C++11 through C++17. Not an aggregate in C++20.
struct B {
B() = delete; // user-declared, but not user-provided
};
// Never an aggregate.
struct C {
C(); // user-declared & user-provided
};
C::C() = default;
As of C++20, this requirement was made more strict to "no user-declared constructors".
Also the standard says: no base classes (Clause 10) but my struct inherits multiply from two aggregate structs Bar and X but still n Aggregate??!
This was the rule in C++11 and C++14. As of C++17 an onwards, it’s more lenient:
1.4) no virtual, private, or protected base classes ([class.mi]).
The standard says: no brace-or-equal-initializers for non-static data members (9.2) but I have initializers for non-static data members x_ and b_ but the compiler still consider Foo as an aggregate struct?? Thank you!
This rule was removed in C++14.