12

I always was under the impression that types like std::is_same, std::is_void, or std::is_aggregate are supposed to inherit from std::integral_constant, or more specifically from std::bool_constant.

However, aggregate classes must not have a base class by definition, but when I use these types as T in std::is_aggregate_v<T>, I get true. So apparently, they are not derived from std::bool_constant?

So my question is:

Why is std::is_aggregate_v<std::is_aggregate<void>> true, at least with GCC and Clang? Doesn't the standard specify that std::is_aggregate is derived from std::bool_constant? If not, does this mean it leaves the value of the above line as an implementation detail?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
x432ph
  • 400
  • 1
  • 10

2 Answers2

12

However, aggregate classes must not have a base class by definition

This is no longer true. [dcl.init.aggr]/1 defines an aggregate as

An aggregate is an array or a class with

  • no user-provided, explicit, or inherited constructors ([class.ctor]),

  • no private or protected non-static data members (Clause [class.access]),

  • no virtual functions, and

  • no virtual, private, or protected base classes ([class.mi]).

[ Note: Aggregate initialization does not allow accessing protected and private base class' members or constructors.  — end note ]

There is no longer a condition that it does not have a base class like it did in C++14 and earlier. As long as it has a public, non virtual base class that is now allowed. This means that the type traits are now considered aggregates as long as the above holds true for them

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
3

Since C++17, classes with non-virtual, not private or protected bases are aggregates: https://en.cppreference.com/w/cpp/language/aggregate_initialization

SergeyA
  • 61,605
  • 5
  • 78
  • 137