2015-09-29 19:21:02 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <boost/operators.hpp>
|
2016-08-23 10:41:08 +00:00
|
|
|
#include <type_traits>
|
2015-09-29 19:21:02 +00:00
|
|
|
|
|
|
|
/** https://svn.boost.org/trac/boost/ticket/5182
|
|
|
|
*/
|
2016-05-12 11:07:30 +00:00
|
|
|
|
2016-08-23 10:41:08 +00:00
|
|
|
template <class T, class Tag>
|
2016-05-12 11:07:30 +00:00
|
|
|
struct StrongTypedef
|
2017-04-01 07:20:54 +00:00
|
|
|
: boost::totally_ordered1< StrongTypedef<T, Tag>
|
|
|
|
, boost::totally_ordered2< StrongTypedef<T, Tag>, T> >
|
2016-05-12 11:07:30 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
using Self = StrongTypedef<T, Tag>;
|
|
|
|
T t;
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
template <class Enable = typename std::is_copy_constructible<T>::type>
|
|
|
|
explicit StrongTypedef(const T & t_) : t(t_) {};
|
|
|
|
template <class Enable = typename std::is_move_constructible<T>::type>
|
|
|
|
explicit StrongTypedef(T && t_) : t(std::move(t_)) {};
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
template <class Enable = typename std::is_default_constructible<T>::type>
|
|
|
|
StrongTypedef(): t() {};
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
StrongTypedef(const Self &) = default;
|
|
|
|
StrongTypedef(Self &&) = default;
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
Self & operator=(const Self &) = default;
|
|
|
|
Self & operator=(Self &&) = default;
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
template <class Enable = typename std::is_copy_assignable<T>::type>
|
|
|
|
Self & operator=(const T & rhs) { t = rhs; return *this;}
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
template <class Enable = typename std::is_move_assignable<T>::type>
|
|
|
|
Self & operator=(T && rhs) { t = std::move(rhs); return *this;}
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
operator const T & () const {return t; }
|
|
|
|
operator T & () { return t; }
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
bool operator==(const Self & rhs) const { return t == rhs.t; }
|
|
|
|
bool operator<(const Self & rhs) const { return t < rhs.t; }
|
2016-08-23 10:41:08 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
T & toUnderType() { return t; }
|
|
|
|
const T & toUnderType() const { return t; }
|
2015-09-29 19:21:02 +00:00
|
|
|
};
|
2016-05-12 11:07:30 +00:00
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
template <class T, class Tag>
|
|
|
|
struct hash<StrongTypedef<T, Tag>>
|
|
|
|
{
|
|
|
|
size_t operator()(const StrongTypedef<T, Tag> & x) const
|
|
|
|
{
|
|
|
|
return std::hash<T>()(x.toUnderType());
|
|
|
|
}
|
|
|
|
};
|
2016-05-12 11:07:30 +00:00
|
|
|
}
|
|
|
|
|
2016-08-23 10:41:08 +00:00
|
|
|
#define STRONG_TYPEDEF(T, D) \
|
2017-04-01 07:20:54 +00:00
|
|
|
struct D ## Tag {}; \
|
|
|
|
using D = StrongTypedef<T, D ## Tag>; \
|
2016-08-23 10:41:08 +00:00
|
|
|
|