That's the final version of my header, now it requires C++20:
#pragma once
#include <type_traits>
template<typename T>
requires std::is_trivially_destructible_v<T>
union ndi_t
{
ndi_t();
ndi_t( T const &init );
ndi_t &operator =( T const &assign );
operator T &();
T *operator &();
T *operator ->()
requires std::is_class_v<T>;
private:
union U
{
U();
U( T const &value );
T m_value;
} m_u;
};
template<typename T>
requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::U::U()
{
}
template<typename T>
requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::U::U( T const &value ) :
m_value( value )
{
}
template<typename T>
requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::ndi_t() :
m_u()
{
}
template<typename T>
requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::ndi_t( T const &init ) :
m_u( init )
{
}
template<typename T>
requires std::is_trivially_destructible_v<T>
inline ndi_t<T> & ndi_t<T>::operator =( T const &assign )
{
m_u.value = assign;
return *this;
}
template<typename T>
requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::operator T &()
{
return m_u.m_value;
}
template<typename T>
requires std::is_trivially_destructible_v<T>
inline T *ndi_t<T>::operator &()
{
return &m_u.m_value;
}
template<typename T>
requires std::is_trivially_destructible_v<T>
inline T *ndi_t<T>::operator ->()
requires std::is_class_v<T>
{
return &m_u.m_value;
}