#pragma once #include template struct no_unique_address_emulation { using stored_type = _Tp; using _Tp::_Tp; _Tp v; inline constexpr _Tp const& ref() const noexcept { return v; } inline constexpr _Tp& ref() noexcept { return v; } }; template struct no_unique_address_emulation<_Tp, _Disambiguator, void, std::enable_if_t>> { using stored_type = _Tp; _Tp v; inline constexpr _Tp const& ref() const noexcept { return v; } inline constexpr _Tp& ref() noexcept { return v; } inline constexpr no_unique_address_emulation() noexcept = default; inline constexpr no_unique_address_emulation(no_unique_address_emulation const&) noexcept = default; inline constexpr no_unique_address_emulation(no_unique_address_emulation&&) noexcept = default; inline constexpr no_unique_address_emulation& operator=(no_unique_address_emulation const&) noexcept = default; inline constexpr no_unique_address_emulation& operator=(no_unique_address_emulation&&) noexcept = default; inline ~no_unique_address_emulation() noexcept = default; inline explicit constexpr no_unique_address_emulation(_Tp const& v) noexcept : _Tp(v) {} inline explicit constexpr no_unique_address_emulation(_Tp&& v) noexcept : _Tp(std::move(v)) {} }; // Empty case // This doesn't work if _Tp is final, of course, but we're not using anything // like that currently. That kind of thing could be added pretty easily though template struct no_unique_address_emulation<_Tp, _Disambiguator, std::enable_if_t && // If the type isn't trivially destructible, its destructor // won't be called at the right time, so don't use this // specialization std::is_trivially_destructible_v<_Tp>>> : protected _Tp { using stored_type = _Tp; using _Tp::_Tp; constexpr _Tp const& ref() const noexcept { return *static_cast<_Tp const*>(this); } constexpr _Tp& ref() noexcept { return *static_cast<_Tp*>(this); } inline constexpr no_unique_address_emulation() noexcept = default; inline constexpr no_unique_address_emulation(no_unique_address_emulation const&) noexcept = default; inline constexpr no_unique_address_emulation(no_unique_address_emulation&&) noexcept = default; inline constexpr no_unique_address_emulation& operator=(no_unique_address_emulation const&) noexcept = default; inline constexpr no_unique_address_emulation& operator=(no_unique_address_emulation&&) noexcept = default; inline ~no_unique_address_emulation() noexcept = default; // Explicitly make this not a reference so that the copy or move // constructor still gets called. inline explicit constexpr no_unique_address_emulation(_Tp const& v) noexcept : _Tp(v) {} inline explicit constexpr no_unique_address_emulation(_Tp&& v) noexcept : _Tp(std::move(v)) {} };