CodeNebula
C++20coreadvanced

Aggregate Initialization with Parentheses (C++20 Evolution)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

Aggregates can be initialized with parentheses, not just braces.

Real-World Scenario

Initialize a struct in a game with a constructor-like syntax.

Quick Snippet

snippet.cpp
struct Point { int x, y; }; Point p(1, 2);

Full Example

aggregate_initialization.cpp
// CodeNebula - C++20 Example: Aggregate Initialization Improvements
// Compile: g++ -std=c++20 -Wall -Wextra -o example aggregate_initialization.cpp

// C++20 improves aggregate initialization in several ways:
//   1. Parenthesized initialization of aggregates: T(args...)
//   2. Designated initializers: T{.member = value}
//   3. CTAD (class template argument deduction) for aggregates

#include <iostream>
#include <array>
#include <string>
#include <memory>

// A simple aggregate (all public, no user-declared constructors)
struct Point {
    double x;
    double y;
    double z;
};

// Aggregate with default member initializers
struct Config {
    std::string name = "default";
    int width = 800;
    int height = 600;
    bool fullscreen = false;
};

// Nested aggregates
struct Line {
    Point start;
    Point end;
};

struct Color {
    unsigned char r, g, b, a;
};

struct ColoredPoint {
    Point position;
    Color color;
    std::string label;
};

void print_point(const Point& p) {
    std::cout << "(" << p.x << ", " << p.y << ", " << p.z << ")";
}

void print_config(const Config& c) {
    std::cout << "Config{name=\"" << c.name << "\", "
              << c.width << "x" << c.height
              << (c.fullscreen ? ", fullscreen" : ", windowed") << "}";
}

int main() {
    std::cout << "=== C++20 Aggregate Initialization ===\n\n";

    // --- Designated initializers (C++20) ---
    std::cout << "Designated initializers:\n";
    Point p1{.x = 1.0, .y = 2.0, .z = 3.0};
    std::cout << "  Point{.x=1, .y=2, .z=3} = ";
    print_point(p1);
    std::cout << "\n";

    // Can skip members — they get default-initialized
    Point p2{.x = 5.0, .z = 10.0};  // y is 0.0
    std::cout << "  Point{.x=5, .z=10}      = ";
    print_point(p2);
    std::cout << "\n";

    // Designated initializers with defaults
    Config cfg{.name = "MyApp", .fullscreen = true};
    std::cout << "  "; print_config(cfg); std::cout << "\n\n";

    // --- Parenthesized initialization of aggregates (C++20) ---
    std::cout << "Parenthesized aggregate init:\n";
    Point p3(10.0, 20.0, 30.0);  // new in C++20!
    std::cout << "  Point(10, 20, 30) = ";
    print_point(p3);
    std::cout << "\n";

    // This enables make_unique/make_shared with aggregates!
    auto ptr = std::make_unique<Point>(1.0, 2.0, 3.0);
    std::cout << "  make_unique<Point>(1,2,3) = ";
    print_point(*ptr);
    std::cout << "\n\n";

    // --- Nested aggregate initialization ---
    std::cout << "Nested aggregates:\n";
    Line line{
        .start = {.x = 0.0, .y = 0.0, .z = 0.0},
        .end   = {.x = 1.0, .y = 1.0, .z = 1.0}
    };
    std::cout << "  Line from ";
    print_point(line.start);
    std::cout << " to ";
    print_point(line.end);
    std::cout << "\n";

    ColoredPoint cp{
        .position = {.x = 5.0, .y = 10.0, .z = 0.0},
        .color    = {255, 0, 128, 255},
        .label    = "marker"
    };
    std::cout << "  ColoredPoint \"" << cp.label << "\" at ";
    print_point(cp.position);
    std::cout << " color=RGBA(" << (int)cp.color.r << ","
              << (int)cp.color.g << "," << (int)cp.color.b << ","
              << (int)cp.color.a << ")\n\n";

    // --- Array initialization ---
    std::cout << "Array aggregate init:\n";
    std::array arr{1, 2, 3, 4, 5};  // CTAD deduces std::array<int,5>
    std::cout << "  std::array{1,2,3,4,5}: ";
    for (int v : arr) std::cout << v << " ";
    std::cout << "\n";

    return 0;
}

// Expected output:
// === C++20 Aggregate Initialization ===
//
// Designated initializers:
//   Point{.x=1, .y=2, .z=3} = (1, 2, 3)
//   Point{.x=5, .z=10}      = (5, 0, 10)
//   Config{name="MyApp", 800x600, fullscreen}
//
// Parenthesized aggregate init:
//   Point(10, 20, 30) = (10, 20, 30)
//   make_unique<Point>(1,2,3) = (1, 2, 3)
//
// Nested aggregates:
//   Line from (0, 0, 0) to (1, 1, 1)
//   ColoredPoint "marker" at (5, 10, 0) color=RGBA(255,0,128,255)
//
// Array aggregate init:
//   std::array{1,2,3,4,5}: 1 2 3 4 5
Run command
g++ -std=c++20 -Wall -Wextra -o example aggregate_initialization.cpp