std::aligned_union(3)

NAME
std::aligned_union - std::aligned_union

Synopsis
   Defined in header <type_traits>
   template< std::size_t Len, class... Types > (since C++11)
   struct aligned_union; (deprecated in C++23)
   Provides the nested type type, which is a trivial standard-layout type of a size and
   alignment suitable for use as uninitialized storage for an object of any of the
   types listed in Types. The size of the storage is at least Len. std::aligned_union
   also determines the strictest (largest) alignment requirement among all Types and
   makes it available as the constant alignment_value.
   If sizeof...(Types) == 0 or if any of the types in Types is not a complete object
   type, the behavior is undefined.
   It is implementation-defined whether any extended alignment is supported.
   The behavior of a program that adds specializations for aligned_union is undefined.

Member types
   Name Definition
   type a trivial and standard-layout type suitable for storage of any type from Types

Helper types
   template< std::size_t Len, class... Types > (since C++14)
   using aligned_union_t = typename (deprecated in C++23)
   aligned_union<Len,Types...>::type;

Member constants
   alignment_value the strictest alignment requirement of all Types
   [static] (public static member constant)

Possible implementation
   #include <algorithm>
   template <std::size_t Len, class... Types>
   struct aligned_union
   {
       static constexpr std::size_t alignment_value = std::max({alignof(Types)...});
       struct type
       {
         alignas(alignment_value) char _s[std::max({Len, sizeof(Types)...})];
       };
   };

Example
// Run this code
 #include <type_traits>
 #include <iostream>
 #include <string>
 int main()
 {
     std::cout
     << sizeof(std::aligned_union_t<0, char>) << ' ' // 1
     << sizeof(std::aligned_union_t<2, char>) << ' ' // 2
     << sizeof(std::aligned_union_t<2, char[3]>) << ' ' // 3 (!)
     << sizeof(std::aligned_union_t<3, char[4]>) << ' ' // 4
     << sizeof(std::aligned_union_t<1, char, int, double>) << ' ' // 8
     << sizeof(std::aligned_union_t<12, char, int, double>) << '\n'; // 16 (!)
     using var_t = std::aligned_union<16, int, std::string>;
     std::cout
     << "var_t::alignment_value = " << var_t::alignment_value << '\n'
     << "sizeof(var_t::type) = " << sizeof(var_t::type) << '\n';
     var_t::type aligned_storage;
     int* int_ptr = new(&aligned_storage) int(42); // placement new
     std::cout << "*int_ptr = " << *int_ptr << '\n';
     std::string* string_ptr = new(&aligned_storage) std::string("bar");
     std::cout << "*string_ptr = " << *string_ptr << '\n';
     *string_ptr = "baz";
     std::cout << "*string_ptr = " << *string_ptr << '\n';
     string_ptr->~basic_string();
 }

Possible output:
 1 2 3 4 8 16
 var_t::alignment_value = 8
 sizeof(var_t::type) = 32
 *int_ptr = 42
 *string_ptr = bar
 *string_ptr = baz
  Defect reports
   The following behavior-changing defect reports were applied retroactively to
   previously published C++ standards.
      DR Applied to Behavior as published Correct behavior
   LWG 2979 C++11 complete type wasn't required requires complete types

See also
   alignment_of obtains the type's alignment requirements
   (C++11) (class template)
   aligned_storage defines the type suitable for use as uninitialized
   (C++11)(deprecated in C++23) storage for types of given size
                        (class template)