1#pragma once
2
3#include <boost/operators.hpp>
4#include <type_traits>
5
6/** https://svn.boost.org/trac/boost/ticket/5182
7 */
8
9template <class T, class Tag>
10struct StrongTypedef
11 : boost::totally_ordered1< StrongTypedef<T, Tag>
12 , boost::totally_ordered2< StrongTypedef<T, Tag>, T> >
13{
14private:
15 using Self = StrongTypedef;
16 T t;
17
18public:
19 template <class Enable = typename std::is_copy_constructible<T>::type>
20 explicit StrongTypedef(const T & t_) : t(t_) {}
21 template <class Enable = typename std::is_move_constructible<T>::type>
22 explicit StrongTypedef(T && t_) : t(std::move(t_)) {}
23
24 template <class Enable = typename std::is_default_constructible<T>::type>
25 StrongTypedef(): t() {}
26
27 StrongTypedef(const Self &) = default;
28 StrongTypedef(Self &&) = default;
29
30 Self & operator=(const Self &) = default;
31 Self & operator=(Self &&) = default;
32
33 template <class Enable = typename std::is_copy_assignable<T>::type>
34 Self & operator=(const T & rhs) { t = rhs; return *this;}
35
36 template <class Enable = typename std::is_move_assignable<T>::type>
37 Self & operator=(T && rhs) { t = std::move(rhs); return *this;}
38
39 operator const T & () const { return t; }
40 operator T & () { return t; }
41
42 bool operator==(const Self & rhs) const { return t == rhs.t; }
43 bool operator<(const Self & rhs) const { return t < rhs.t; }
44
45 T & toUnderType() { return t; }
46 const T & toUnderType() const { return t; }
47};
48
49namespace std
50{
51 template <class T, class Tag>
52 struct hash<StrongTypedef<T, Tag>>
53 {
54 size_t operator()(const StrongTypedef<T, Tag> & x) const
55 {
56 return std::hash<T>()(x.toUnderType());
57 }
58 };
59}
60
61#define STRONG_TYPEDEF(T, D) \
62 struct D ## Tag {}; \
63 using D = StrongTypedef<T, D ## Tag>; \
64
65