You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

69 lines
3.5 KiB

#pragma once
#include <type_traits>
template <class _Tp, size_t _Disambiguator = 0, class _Enable = void, class _Is_Fundamental = void>
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 <class _Tp, size_t _Disambiguator>
struct no_unique_address_emulation<_Tp, _Disambiguator, void, std::enable_if_t<std::is_fundamental_v<_Tp>>> {
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 <class _Tp, size_t _Disambiguator>
struct no_unique_address_emulation<_Tp,
_Disambiguator,
std::enable_if_t<std::is_empty_v<_Tp> &&
// 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)) {}
};