Aggregate

注意,有 bit fields 或者 有成员默认值 或者 有匿名 union 成员 也可以是 aggregate。

对含有 union 成员的聚合类使用 花括号默认的全参数构造函数 初始化时,初始化的是 union 的第一个元素(不管 union 是不是匿名的)。

(C++20) 隐式提供的的全参数构造函数

#include <iostream>
#include <vector>

struct Point {
    double x;
    double y;
};

int main() {
    std::vector<Point> points;
    // 可以省略类型,花括号自动推导。
    points.push_back({1, 1});
    // 必须要写Point类型。因为是模板参数,捕获的时候不知道目的类型,不能推导。
    points.emplace_back(Point{1, 1});
    // 下面两行在 C++20 可以编译:
    points.emplace_back(1, 2);
    auto some_point = Point(1, 2);
}

注意这样的全参数构造函数是具有 explicit 属性的。所以下面的代码不能编译:

struct Id { int value; };
int main() {
    Id some_id = 4;
}

作为模板的非类型参数?

不是所有的聚合类都能作为非类型参数!一个反例:定义了析构函数的聚合类不能作为 NTTP。

这是类类型模板非类型参数(C++ 20)引入后,部分聚合类 作为特殊情况享受到的一种好处。

结构化绑定?

不是所有的聚合类都能结构化绑定! 反例是含有匿名 union 成员的聚合类不能被结构化绑定。

部分聚合类也能够使用结构化绑定。见 结构化绑定(Structured Binding)

struct Point {
    double x{-1};
    double y;
};

int main() {
    auto [x, y] = Point{1.5, 2.0};
    static_assert(std::is_aggregate_v<Point>); // true
}