Search code examples
c++c++20unionsctad

How to write a deduction guide for union type


Let's suppose we have this template for a union of a struct and an array of bytes of the same size

template<typename T>
union point {
    struct { T x, y; } coord;
    static constexpr size_t buffer_size = sizeof(coord);
    unsigned char buffer[buffer_size];
};

and we would like to use CTAD and aggregate initialization in client code following to C++17

auto p1 = point { .coord = { 0.1, 0.2 } };
auto p2 = point { .coord = { 1, 2 } };

The compiler expects us a deduction guide for point type. How it can be defined in case of union type?


Solution

  • Deduction guides are based on constructors, either hypothetical ones created by explicit deduction guides or those that actually exist. Designated initializers are a form of aggregate initialization, and a type can only be an aggregate if it has no constructors.

    While that might still allow explicit deduction guides, that would only work if the list initialization syntax could select a constructor. But a braced-init-list that contains a designated initializer cannot select a constructor.

    In short, you cannot combine designated initializers and CTAD. At all.

    Note that you can use CTAD with unions generally, but that would require writing constructors and possibly using tagged dispatch to specify which member each constructor initializes. The problem comes from trying to initialize the union as an aggregate.