-
Notifications
You must be signed in to change notification settings - Fork 1
/
enum.h++
131 lines (123 loc) · 4.03 KB
/
enum.h++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifndef ENUM_HPP
#define ENUM_HPP
#include <ostream>
#include <string>
#include <exception>
namespace Enum {
static const char ENUM_HPP_SCCS_ID[] __attribute__((used)) = "@(#)enum.h++: $Id$";
template<const char *id>
class Enum {
static int n;
public:
class badsize: public std::exception {
const std::string msg;
public:
virtual const char *what() const noexcept override {return msg.c_str();}
badsize(const std::string &s): msg(s) {}
badsize(std::string &&s): msg(std::forward<std::string>(s)) {}
constexpr badsize() = delete;
};
static void setn(const int newn) {
if (n)
throw badsize(std::string("Size of Enum<")+std::string(id)
+ std::string("> already set"));
else
n = newn;
}
static int getn() { return n; }
friend inline std::ostream& operator<< (std::ostream& o, const Enum& e) {
return o << std::string(id) << static_cast<int>(e);
}
constexpr int uniqid() const {return val;}
virtual double match(const Enum& m) const {
return m==*this?1.0-1.0*(n-1)/(n*n):1.0/(n*n);
}
virtual Enum& operator=(const Enum& m){
static_cast<int&>(*this)=static_cast<int>(m);
return *this;
}
constexpr Enum(const Enum &m):val(static_cast<int>(m)){}
explicit Enum(const int val):val(val){
if (!n)
throw badsize(std::string("Size of Enum<")+std::string(id)
+ std::string("> not set"));
}
protected:
virtual ~Enum(void) = default; // virtual to force derived classes to have virtual destructors
private:
int val;
Enum(void):val(-1){
if (!n)
throw badsize(std::string("Size of Enum<")+std::string(id)
+ std::string("> not set"));
}
static int number(void) {return n;}
explicit operator int& (void) {return val;}
/*
constexpr Enum operator+(const Enum &i) const {
return Enum(static_cast<int>(*this)+static_cast<int>(i));
}
constexpr Enum operator-(const Enum &i) const {
return Enum(static_cast<int>(*this)-static_cast<int>(i));
}
*/
constexpr Enum operator+(const int i) const {
return Enum(static_cast<int>(*this)+static_cast<int>(i));
}
constexpr Enum operator-(const int i) const {
return Enum(static_cast<int>(*this)-static_cast<int>(i));
}
Enum& operator++(void) {
static_cast<int&>(*this)++; return *this;
}
Enum operator++(int) {
auto ret(*this);
static_cast<int&>(*this)++;
return ret;
}
Enum& operator--(void) {
static_cast<int&>(*this)--; return *this;
}
Enum operator--(int) {
auto ret(*this);
static_cast<int&>(*this)--;
return ret;}
Enum& operator+=(const Enum &i) {
static_cast<int&>(*this)+=static_cast<int>(i);
return *this;
}
Enum& operator-=(const Enum &i) {
static_cast<int&>(*this)+=static_cast<int>(i);
return *this;
}
public:
// This conversion operatore was private in Tanmoy's original code, but needs to be
// public if we want to be able to interpret the Enum as a sequence of bits
explicit constexpr operator int (void) const {return val;}
// These comparison operators were private in Tanmoy's original code, but need to be
// public if we want to use Enums in a map key
constexpr bool operator<(const Enum &other) const {
return static_cast<int>(*this) < static_cast<int>(other);
}
constexpr bool operator>(const Enum &other) const {
return static_cast<int>(*this) > static_cast<int>(other);
}
constexpr bool operator<=(const Enum &other) const {
return static_cast<int>(*this) <= static_cast<int>(other);
}
constexpr bool operator>=(const Enum &other) const {
return static_cast<int>(*this) >= static_cast<int>(other);
}
constexpr bool operator==(const Enum &other) const {
return static_cast<int>(*this) == static_cast<int>(other);
}
constexpr bool operator!=(const Enum &other) const {
return static_cast<int>(*this) != static_cast<int>(other);
}
// template<typename,typename> friend class Enumvector;
template<typename,bool> friend class SelfIterator::SelfIterator;
template<typename,bool> friend class SelfIterator::Range;
// template<typename T> friend auto range(T);
};
}
#endif