osb/source/core/StarStrongTypedef.hpp

103 lines
7.2 KiB
C++
Raw Permalink Normal View History

#pragma once
2023-06-20 04:33:09 +00:00
#include <type_traits>
// Defines a new type that behaves nearly identical to 'parentType', with the
// added benefit that though the new type can be implicitly converted to the
// base type, it must be explicitly converted *from* the base type, and they
// are two distinct types in the type system.
#define strong_typedef(ParentType, NewType) \
template <typename BaseType> \
struct NewType##Wrapper : BaseType { \
using BaseType::BaseType; \
\
NewType##Wrapper() : BaseType() {} \
\
NewType##Wrapper(NewType##Wrapper const& nt) : BaseType(nt) {} \
\
NewType##Wrapper(NewType##Wrapper&& nt) : BaseType(std::move(nt)) {} \
\
explicit NewType##Wrapper(BaseType const& bt) : BaseType(bt) {} \
\
explicit NewType##Wrapper(BaseType&& bt) : BaseType(std::move(bt)) {} \
\
NewType##Wrapper& operator=(NewType##Wrapper const& rhs) { \
BaseType::operator=(rhs); \
return *this; \
} \
\
NewType##Wrapper& operator=(NewType##Wrapper&& rhs) { \
BaseType::operator=(std::move(rhs)); \
return *this; \
} \
\
template <class Arg> \
NewType##Wrapper& operator=(Arg&& other) { \
static_assert(std::is_base_of<BaseType, typename std::decay<Arg>::type>::value == false \
|| std::is_same<NewType##Wrapper, typename std::decay<Arg>::type>::value, \
"" #NewType " can not implicitly be assigned from " #ParentType "-derived classes or strong " #ParentType \
" typedefs"); \
\
BaseType::operator=(std::forward<Arg>(other)); \
return *this; \
} \
}; \
typedef NewType##Wrapper<ParentType> NewType
// Version of strong_typedef for builtin types.
#define strong_typedef_builtin(Type, NewType) \
struct NewType { \
Type t; \
\
explicit NewType(const Type t_) \
: t(t_){}; \
\
NewType() \
: t(Type()) {} \
\
NewType(const NewType& t_) \
: t(t_.t) {} \
\
NewType& operator=(const NewType& rhs) { \
t = rhs.t; \
return *this; \
} \
\
NewType& operator=(Type const& rhs) { \
t = rhs; \
return *this; \
} \
\
operator const Type&() const { \
return t; \
} \
\
operator Type&() { \
return t; \
} \
\
bool operator==(NewType const& rhs) const { \
return t == rhs.t; \
} \
\
bool operator!=(NewType const& rhs) const { \
return t != rhs.t; \
} \
\
bool operator<(NewType const& rhs) const { \
return t < rhs.t; \
} \
\
bool operator>(NewType const& rhs) const { \
return t > rhs.t; \
} \
\
bool operator<=(NewType const& rhs) const { \
return t <= rhs.t; \
} \
\
bool operator>=(NewType const& rhs) const { \
return t >= rhs.t; \
} \
}