Skip to content

Commit

Permalink
Support constexpr for arithmetic strong_typedef_ops (foonathan#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohelEGP authored and foonathan committed Nov 14, 2017
1 parent 8191a8f commit c552b16
Showing 1 changed file with 79 additions and 26 deletions.
105 changes: 79 additions & 26 deletions include/type_safe/strong_typedef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,13 @@ namespace type_safe
return get(type);
}

template <class StrongTypedef>
TYPE_SAFE_CONSTEXPR14 underlying_type<StrongTypedef>& get_underlying(
StrongTypedef& type)
{
return get(static_cast<StrongTypedef&>(type));
}

template <class StrongTypedef>
TYPE_SAFE_CONSTEXPR14 underlying_type<StrongTypedef>&& get_underlying(
StrongTypedef&& type)
Expand Down Expand Up @@ -291,50 +298,96 @@ namespace type_safe
}

/// \exclude
#define TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND(Op, Other) \
#define TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND(Op, Name) \
/** \exclude */ \
friend StrongTypedef& operator Op(StrongTypedef& lhs, const Other& rhs) \
template <class StrongTypedef> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef& operator Op(Name<StrongTypedef>& lhs, \
const Name<StrongTypedef>& rhs) \
{ \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&>(lhs)) Op \
detail::get_underlying<StrongTypedef>(static_cast<const StrongTypedef&>(rhs)); \
return static_cast<StrongTypedef&>(lhs); \
} /** \exclude */ \
template <class StrongTypedef> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef& operator Op(Name<StrongTypedef>& lhs, \
Name<StrongTypedef>&& rhs) \
{ \
using type = underlying_type<StrongTypedef>; \
static_cast<type&>(lhs) Op static_cast<const type&>(rhs); \
return lhs; \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&>(lhs)) Op \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&&>(rhs)); \
return static_cast<StrongTypedef&>(lhs); \
} \
/** \exclude */ \
friend StrongTypedef& operator Op(StrongTypedef& lhs, Other&& rhs) \
template <class StrongTypedef> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef&& operator Op(Name<StrongTypedef>&& lhs, \
const Name<StrongTypedef>& rhs) \
{ \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&&>(lhs)) Op \
detail::get_underlying<StrongTypedef>(static_cast<const StrongTypedef&>(rhs)); \
return static_cast<StrongTypedef&&>(lhs); \
} /** \exclude */ \
template <class StrongTypedef> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef&& operator Op(Name<StrongTypedef>&& lhs, \
Name<StrongTypedef>&& rhs) \
{ \
using type = underlying_type<StrongTypedef>; \
static_cast<type&>(lhs) Op std::move(static_cast<type&>(rhs)); \
return lhs; \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&&>(lhs)) Op \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&&>(rhs)); \
return static_cast<StrongTypedef&&>(lhs); \
} \
/* mixed */ \
/** \exclude */ \
friend StrongTypedef&& operator Op(StrongTypedef&& lhs, const Other& rhs) \
template <class StrongTypedef, typename Other, \
typename = detail::enable_if_convertible<Other&&, StrongTypedef>> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef& operator Op(Name<StrongTypedef>& lhs, Other&& rhs) \
{ \
using type = underlying_type<StrongTypedef>; \
std::move(static_cast<type&>(lhs)) Op static_cast<const type&>(rhs); \
return std::move(lhs); \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&>(lhs)) \
Op detail::get_underlying<StrongTypedef>(detail::forward<Other>(rhs)); \
return static_cast<StrongTypedef&>(lhs); \
} \
/** \exclude */ \
friend StrongTypedef&& operator Op(StrongTypedef&& lhs, Other&& rhs) \
template <class StrongTypedef, typename Other, \
typename = detail::enable_if_convertible<Other&&, StrongTypedef>> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef&& operator Op(Name<StrongTypedef>&& lhs, Other&& rhs) \
{ \
detail::get_underlying<StrongTypedef>(static_cast<StrongTypedef&&>(lhs)) \
Op detail::get_underlying<StrongTypedef>(detail::forward<Other>(rhs)); \
return static_cast<StrongTypedef&&>(lhs); \
}

/// \exclude
#define TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND_MIXED(Op, Name) \
/** \exclude */ \
template <class StrongTypedef, typename OtherArg, typename Other, \
typename = detail::enable_if_convertible_same<Other&&, OtherArg>> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef& operator Op(Name<StrongTypedef, OtherArg>& lhs, \
Other&& rhs) \
{ \
get(static_cast<StrongTypedef&>(lhs)) Op detail::forward<Other>(rhs); \
return static_cast<StrongTypedef&>(lhs); \
} \
/** \exclude */ \
template <class StrongTypedef, typename OtherArg, typename Other, \
typename = detail::enable_if_convertible_same<Other&&, OtherArg>> \
TYPE_SAFE_CONSTEXPR14 StrongTypedef&& operator Op(Name<StrongTypedef, OtherArg>&& lhs, \
Other&& rhs) \
{ \
using type = underlying_type<StrongTypedef>; \
std::move(static_cast<type&>(lhs)) Op std::move(static_cast<type&>(rhs)); \
return std::move(lhs); \
get(static_cast<StrongTypedef&&>(lhs)) Op detail::forward<Other>(rhs); \
return static_cast<StrongTypedef&&>(lhs); \
}

/// \exclude
#define TYPE_SAFE_DETAIL_MAKE_STRONG_TYPEDEF_OP(Name, Op) \
template <class StrongTypedef> \
struct Name \
{ \
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND(Op## =, StrongTypedef) \
}; \
TYPE_SAFE_DETAIL_MAKE_OP(Op, Name, StrongTypedef) \
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND(Op## =, Name) \
template <class StrongTypedef, typename Other> \
struct mixed_##Name \
{ \
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND(Op## =, Other) \
}; \
TYPE_SAFE_DETAIL_MAKE_OP_MIXED(Op, mixed_##Name, StrongTypedef)
TYPE_SAFE_DETAIL_MAKE_OP_MIXED(Op, mixed_##Name, StrongTypedef) \
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND_MIXED(Op## =, mixed_##Name)

template <class StrongTypedef>
struct equality_comparison
Expand Down Expand Up @@ -378,15 +431,15 @@ namespace type_safe
struct increment
{
/// \exclude
StrongTypedef& operator++()
TYPE_SAFE_CONSTEXPR14 StrongTypedef& operator++()
{
using type = underlying_type<StrongTypedef>;
++static_cast<type&>(static_cast<StrongTypedef&>(*this));
return static_cast<StrongTypedef&>(*this);
}

/// \exclude
StrongTypedef operator++(int)
TYPE_SAFE_CONSTEXPR14 StrongTypedef operator++(int)
{
auto result = static_cast<StrongTypedef&>(*this);
++*this;
Expand All @@ -398,15 +451,15 @@ namespace type_safe
struct decrement
{
/// \exclude
StrongTypedef& operator--()
TYPE_SAFE_CONSTEXPR14 StrongTypedef& operator--()
{
using type = underlying_type<StrongTypedef>;
--static_cast<type&>(static_cast<StrongTypedef&>(*this));
return static_cast<StrongTypedef&>(*this);
}

/// \exclude
StrongTypedef operator--(int)
TYPE_SAFE_CONSTEXPR14 StrongTypedef operator--(int)
{
auto result = static_cast<StrongTypedef&>(*this);
--*this;
Expand Down Expand Up @@ -506,11 +559,11 @@ namespace type_safe
template <class StrongTypedef, typename IntT>
struct bitshift
{
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND(<<=, IntT)
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND(>>=, IntT)
};
TYPE_SAFE_DETAIL_MAKE_OP_MIXED(<<, bitshift, StrongTypedef)
TYPE_SAFE_DETAIL_MAKE_OP_MIXED(>>, bitshift, StrongTypedef)
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND_MIXED(<<=, bitshift)
TYPE_SAFE_DETAIL_MAKE_OP_COMPOUND_MIXED(>>=, bitshift)

template <class StrongTypedef, typename Result, typename ResultPtr = Result*,
typename ResultConstPtr = const Result*>
Expand Down

0 comments on commit c552b16

Please sign in to comment.