-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathstatic_isa.h
139 lines (119 loc) · 4.39 KB
/
static_isa.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
132
133
134
135
136
137
138
#include "conversion_detection.h"
//////////////////////////////////////////////////////////////////////
// For custom error messages
//////////////////////////////////////////////////////////////////////
template <class T>
struct Error {};
//////////////////////////////////////////////////////////////////////
// BoolError<false> doesn't exist; used to create errors from booleans
//////////////////////////////////////////////////////////////////////
template <bool b>
struct BoolError;
template <>
struct BoolError<true> {};
//////////////////////////////////////////////////////////////////////
// Usual meta-IF
//////////////////////////////////////////////////////////////////////
template <bool b, class T, class E>
struct IF;
template <class T, class E>
struct IF<true,T,E> {
typedef T RET;
};
template <class T, class E>
struct IF<false,T,E> {
typedef E RET;
};
//////////////////////////////////////////////////////////////////////
// A way to thunk an int; not useful by itself, but useful to make "then"
// and "else" clauses of IF parallel
//////////////////////////////////////////////////////////////////////
template <int N>
struct IntHolderThunk {
template <class T>
struct Value {
static const int RET = N;
};
};
//////////////////////////////////////////////////////////////////////
// This class helps us instantiate a template method during the act of
// accessing a compile-time constant value
//////////////////////////////////////////////////////////////////////
template <void (*F)()>
struct Blah { static const int x = 1; };
//////////////////////////////////////////////////////////////////////
// This just makes it easier to instantiate the check_structural()
// function of a static interface
//////////////////////////////////////////////////////////////////////
template <class T, class I>
void check_structural() {
(void) ((void (I::*)(T)) &I::template check_structural<T>);
}
//////////////////////////////////////////////////////////////////////
// StaticIsA
//////////////////////////////////////////////////////////////////////
template <class Derived, class Base>
struct StaticIsA {
// Note to self: need to bootstrap this, as there's a constraint! :)
static const bool builtin_isa = Base::template Traits<Derived>::valid;
static const bool named_isa = Inherits<Derived,Base>::value;
struct Thunk {
template <class Dummy>
struct Value {
static const int RET =
Blah<&check_structural<Derived,Base> >::x;
};
};
typedef typename IF<named_isa,
Thunk,IntHolderThunk<builtin_isa> >::RET Compute;
// "valid" is true if the relationship holds; will also diagnose
// structural conformance problems if any
static const bool valid = Compute::template Value<int>::RET;
};
//////////////////////////////////////////////////////////////////////
// Named
//////////////////////////////////////////////////////////////////////
template <class Derived, class Base>
struct Named {
static const bool valid = Inherits<Derived,Base>::value;
};
//////////////////////////////////////////////////////////////////////
// RequireStructural
//////////////////////////////////////////////////////////////////////
template <class T, class Concept>
inline void RequireStructural() {
(void) ((void (*)()) &check_structural<T,Concept>);
}
//////////////////////////////////////////////////////////////////////
// RequireNamed
//////////////////////////////////////////////////////////////////////
template <class T, class Concept>
inline void RequireNamed() {
BoolError< Named<T,Concept>::valid > RequireNamed_has_failed;
(void) RequireNamed_has_failed;
}
//////////////////////////////////////////////////////////////////////
// RequireBoth
//////////////////////////////////////////////////////////////////////
template <class T, class Concept>
inline void RequireBoth() {
RequireNamed<T,Concept>();
RequireStructural<T,Concept>();
}
//////////////////////////////////////////////////////////////////////
// This stuff is just to help users define static interfaces easily
//////////////////////////////////////////////////////////////////////
#define MAKE_TRAITS \
template <class Self> \
struct Traits { \
static const bool valid = false; \
};
struct Valid {
static const bool valid = true;
protected:
~Valid() {};
};
template <class T>
struct HeroicProxy {
HeroicProxy( const T& ) {}
};