Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- // Helper namespace that uses SFINAE to check for certain operators.
- namespace check_operator_impl {
- typedef char NO;
- typedef char YES[2];
- struct Any {
- template <typename T> Any(T const&);
- };
- NO operator < (const Any&, const Any&);
- NO operator <= (const Any&, const Any&);
- NO operator == (const Any&, const Any&);
- NO operator >= (const Any&, const Any&);
- NO operator > (const Any&, const Any&);
- NO operator != (const Any&, const Any&);
- YES& test(bool);
- NO test(NO);
- template <typename T> struct HasLessThanOperator
- { static const T& t; static bool const value = sizeof(test(t < t)) == sizeof(YES); };
- template <typename T> struct HasLessThanOrEqualOperator
- { static const T& t; static bool const value = sizeof(test(t <= t)) == sizeof(YES); };
- template <typename T> struct HasEqualOperator
- { static const T& t; static bool const value = sizeof(test(t == t)) == sizeof(YES); };
- template <typename T> struct HasGreaterThanOrEqualOperator
- { static const T& t; static bool const value = sizeof(test(t >= t)) == sizeof(YES); };
- template <typename T> struct HasGreaterThanOperator
- { static const T& t; static bool const value = sizeof(test(t > t)) == sizeof(YES); };
- template <typename T> struct HasUnequalOperator
- { static const T& t; static bool const value = sizeof(test(t != t)) == sizeof(YES); };
- }
- // The actual value container.
- template <typename T>
- struct ValueBase
- {
- ValueBase() { }
- ValueBase(const T& value) : m_value(value) { }
- const T& value() const { return m_value; }
- T& value() { return m_value; }
- T m_value;
- };
- // Wrappers for various common operators.
- template <typename T, typename Meaning, bool do_wrap>
- struct WrapLessThanOperatorImpl : public virtual ValueBase<T> { };
- template <typename T, typename Meaning, bool do_wrap>
- struct WrapLessThanOrEqualOperatorImpl : public virtual ValueBase<T> { };
- template <typename T, typename Meaning, bool do_wrap>
- struct WrapEqualOperatorImpl : public virtual ValueBase<T> { };
- template <typename T, typename Meaning, bool do_wrap>
- struct WrapGreaterThanOrEqualOperatorImpl : public virtual ValueBase<T> { };
- template <typename T, typename Meaning, bool do_wrap>
- struct WrapGreaterThanOperatorImpl : public virtual ValueBase<T> { };
- template <typename T, typename Meaning, bool do_wrap>
- struct WrapUnequalOperatorImpl : public virtual ValueBase<T> { };
- // Wrap the operators if T has such operators.
- template <typename T, typename Meaning>
- struct WrapLessThanOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
- {
- bool operator < (const WrapLessThanOperatorImpl<T, Meaning, true>& other)
- { return ValueBase<T>::value() < other.ValueBase<T>::value(); }
- };
- template <typename T, typename Meaning>
- struct WrapLessThanOrEqualOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
- {
- bool operator <= (const WrapLessThanOrEqualOperatorImpl<T, Meaning, true>& other)
- { return ValueBase<T>::value() <= other.ValueBase<T>::value(); }
- };
- template <typename T, typename Meaning>
- struct WrapEqualOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
- {
- bool operator == (const WrapEqualOperatorImpl<T, Meaning, true>& other)
- { return ValueBase<T>::value() == other.ValueBase<T>::value(); }
- };
- template <typename T, typename Meaning>
- struct WrapGreaterThanOrEqualOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
- {
- bool operator>= (const WrapGreaterThanOrEqualOperatorImpl<T, Meaning, true>& other)
- { return ValueBase<T>::value() >= other.ValueBase<T>::value(); }
- };
- template <typename T, typename Meaning>
- struct WrapGreaterThanOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
- {
- bool operator > (const WrapGreaterThanOperatorImpl<T, Meaning, true>& other)
- { return ValueBase<T>::value() > other.ValueBase<T>::value(); }
- };
- template <typename T, typename Meaning>
- struct WrapUnequalOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
- {
- bool operator != (const WrapUnequalOperatorImpl<T, Meaning, true>& other)
- { return ValueBase<T>::value() != other.ValueBase<T>::value(); }
- };
- // These wrappers are just for convenience.
- template <typename T, typename Meaning>
- struct WrapLessThanOperator
- : public WrapLessThanOperatorImpl<
- T, Meaning,
- check_operator_impl::HasLessThanOperator<T>::value>
- { };
- template <typename T, typename Meaning>
- struct WrapLessThanOrEqualOperator
- : public WrapLessThanOrEqualOperatorImpl<
- T, Meaning,
- check_operator_impl::HasLessThanOrEqualOperator<T>::value>
- { };
- template <typename T, typename Meaning>
- struct WrapEqualOperator
- : public WrapEqualOperatorImpl<
- T, Meaning,
- check_operator_impl::HasEqualOperator<T>::value>
- { };
- template <typename T, typename Meaning>
- struct WrapGreaterThanOrEqualOperator
- : public WrapGreaterThanOrEqualOperatorImpl<
- T, Meaning,
- check_operator_impl::HasGreaterThanOrEqualOperator<T>::value>
- { };
- template <typename T, typename Meaning>
- struct WrapGreaterThanOperator
- : public WrapGreaterThanOperatorImpl<
- T, Meaning,
- check_operator_impl::HasGreaterThanOperator<T>::value>
- { };
- template <typename T, typename Meaning>
- struct WrapUnequalOperator
- : public WrapUnequalOperatorImpl<
- T, Meaning,
- check_operator_impl::HasUnequalOperator<T>::value>
- { };
- // Now for the actual Explicit class.
- template <typename T, typename Meaning>
- struct Explicit : public WrapLessThanOperator<T, Meaning>,
- public WrapLessThanOrEqualOperator<T, Meaning>,
- public WrapEqualOperator<T, Meaning>,
- public WrapGreaterThanOrEqualOperator<T, Meaning>,
- public WrapGreaterThanOperator<T, Meaning>,
- public WrapUnequalOperator<T, Meaning>
- {
- //! Default constructor does not initialize the value.
- Explicit()
- { }
- //! Construction from a fundamental value.
- Explicit(const T& value)
- : ValueBase<T>(value)
- { }
- Explicit& operator = (const T& value_)
- { ValueBase<T>::value() = value_; return *this; }
- };
- // Define some tags.
- namespace internal {
- struct EntityIDTag { };
- struct ModelIDTag { };
- }
- // Some explicit integers
- typedef Explicit<int, internal::EntityIDTag> EntityID;
- typedef Explicit<int, internal::ModelIDTag> ModelID;
- // Let's make some explicit Foos, just to show that it works if you
- // don't have all the operators.
- struct Foo
- {
- Foo() { }
- explicit Foo(int value) : value(value) { }
- int value;
- bool operator < (const Foo& other) const { return value < other.value; }
- };
- typedef Explicit<Foo, internal::EntityIDTag> EntityFoo;
- typedef Explicit<Foo, internal::ModelIDTag> ModelFoo;
- int main()
- {
- EntityID e1 = 1, e2 = 2;
- ModelID m1 = 3, m2 = 4;
- EntityFoo e3(Foo(5));
- ModelFoo m3(Foo(6));
- m1 = m2; // OK
- // e1 = m1; // no match for 'operator=' in 'e1 = m1'
- if (e1 == e2) { } // OK
- if (e1 <= e2) { } // OK
- // if (m1 == e2) { } // no match for operator==
- // if (e3 == e3) { } // Foo has no operator==
- if (e3 < e3) { } // OK, operator exists
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement