Skip to content

Instantly share code, notes, and snippets.

@SergNikitin
Created October 20, 2016 19:17
Show Gist options
  • Save SergNikitin/587b30585ad5bc87585cb6b0eafba45e to your computer and use it in GitHub Desktop.
Save SergNikitin/587b30585ad5bc87585cb6b0eafba45e to your computer and use it in GitHub Desktop.
explicit id v2
template <typename T, typename UniqueTag>
class ExplicitArithmeticID final
{
public:
using UnderlyingType = T;
static_assert(std::is_arithmetic<UnderlyingType>::value,
"ExplicitArithmeticID is for arithmetic types only");
constexpr explicit ExplicitArithmeticID(UnderlyingType value)
: mUnderlyingValue(value)
{
}
// TODO [snikitin@outlook.com] Should default construction be allowed?
constexpr ExplicitArithmeticID() = default;
constexpr const UnderlyingType& underlying() const
{
return mUnderlyingValue;
}
constexpr bool operator==(ExplicitArithmeticID) const;
constexpr bool operator!=(ExplicitArithmeticID) const;
constexpr bool operator<(ExplicitArithmeticID) const;
constexpr bool operator<=(ExplicitArithmeticID) const;
constexpr bool operator>(ExplicitArithmeticID) const;
constexpr bool operator>=(ExplicitArithmeticID) const;
private:
UnderlyingType mUnderlyingValue;
};
template <typename T, typename UTag>
constexpr bool ExplicitArithmeticID<T, UTag>::operator==(ExplicitArithmeticID other) const
{
return mUnderlyingValue == other.mUnderlyingValue;
}
template <typename T, typename UTag>
constexpr bool ExplicitArithmeticID<T, UTag>::operator!=(ExplicitArithmeticID other) const
{
return !operator==(other);
}
template <typename T, typename UTag>
constexpr bool ExplicitArithmeticID<T, UTag>::operator<(ExplicitArithmeticID other) const
{
return mUnderlyingValue < other.mUnderlyingValue;
}
template <typename T, typename UTag>
constexpr bool ExplicitArithmeticID<T, UTag>::operator<=(ExplicitArithmeticID other) const
{
return mUnderlyingValue <= other.mUnderlyingValue;
}
template <typename T, typename UTag>
constexpr bool ExplicitArithmeticID<T, UTag>::operator>(ExplicitArithmeticID other) const
{
return mUnderlyingValue > other.mUnderlyingValue;
}
template <typename T, typename UTag>
constexpr bool ExplicitArithmeticID<T, UTag>::operator>=(ExplicitArithmeticID other) const
{
return mUnderlyingValue >= other.mUnderlyingValue;
}
template <typename T, typename... Types>
struct IsExplicitArithmeticID : std::false_type {};
template <typename... Types>
struct IsExplicitArithmeticID<ExplicitArithmeticID<Types...>> : std::true_type {};
namespace std
{
template <typename T, typename UniqueTag>
struct hash<ExplicitArithmeticID<T, UniqueTag>>
{
size_t operator()(ExplicitArithmeticID<T, UniqueTag> value) const
{
return std::hash<T>{}(value.underlying());
}
};
} // namespace std
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment