@@ -29,77 +29,36 @@ namespace llvm {
29
29
class raw_ostream ;
30
30
31
31
namespace optional_detail {
32
-
33
32
// / Storage for any type.
34
- //
35
- template <class T > struct OptionalTrivialStorage {
33
+ template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalStorage {
36
34
AlignedCharArrayUnion<T> storage;
37
35
bool hasVal = false ;
38
- OptionalTrivialStorage () = default ;
39
- OptionalTrivialStorage (OptionalTrivialStorage const &) = default ;
40
- OptionalTrivialStorage (OptionalTrivialStorage &&) = default ;
41
- OptionalTrivialStorage &operator =(OptionalTrivialStorage const &) = default ;
42
- OptionalTrivialStorage &operator =(OptionalTrivialStorage &&) = default ;
43
- ~OptionalTrivialStorage () = default ;
44
-
45
- OptionalTrivialStorage (const T &y) : hasVal(true ) {
46
- new (storage.buffer ) T (y);
47
- }
48
- OptionalTrivialStorage (T &&y) : hasVal(true ) {
49
- new (storage.buffer ) T (std::move (y));
50
- }
51
-
52
- OptionalTrivialStorage &operator =(const T &y) {
53
- new (storage.buffer ) T (y);
54
- hasVal = true ;
55
- return *this ;
56
- }
57
- OptionalTrivialStorage &operator =(T &&y) {
58
- new (storage.buffer ) T (std::move (y));
59
- hasVal = true ;
60
- return *this ;
61
- }
62
-
63
- T *getPointer () {
64
- assert (hasVal);
65
- return reinterpret_cast <T *>(storage.buffer );
66
- }
67
- const T *getPointer () const {
68
- assert (hasVal);
69
- return reinterpret_cast <const T *>(storage.buffer );
70
- }
71
- void reset () { hasVal = false ; }
72
- };
73
-
74
- template <typename T> struct OptionalStorage : OptionalTrivialStorage<T> {
75
36
76
37
OptionalStorage () = default ;
77
38
78
- OptionalStorage (const T &y) : OptionalTrivialStorage<T>(y) {}
79
- OptionalStorage (T &&y) : OptionalTrivialStorage<T>(std::move(y)) {}
80
-
81
- OptionalStorage (const OptionalStorage &O) : OptionalTrivialStorage<T>() {
82
- this ->hasVal = O.hasVal ;
83
- if (this ->hasVal )
84
- new (this ->storage .buffer ) T (*O.getPointer ());
39
+ OptionalStorage (const T &y) : hasVal(true ) { new (storage.buffer ) T (y); }
40
+ OptionalStorage (const OptionalStorage &O) : hasVal(O.hasVal) {
41
+ if (hasVal)
42
+ new (storage.buffer ) T (*O.getPointer ());
85
43
}
86
-
87
- OptionalStorage (OptionalStorage &&O) : OptionalTrivialStorage<T>() {
88
- this ->hasVal = O.hasVal ;
44
+ OptionalStorage (T &&y) : hasVal(true ) {
45
+ new (storage.buffer ) T (std::forward<T>(y));
46
+ }
47
+ OptionalStorage (OptionalStorage &&O) : hasVal(O.hasVal) {
89
48
if (O.hasVal ) {
90
- new (this -> storage .buffer ) T (std::move (*O.getPointer ()));
49
+ new (storage.buffer ) T (std::move (*O.getPointer ()));
91
50
}
92
51
}
93
52
94
53
OptionalStorage &operator =(T &&y) {
95
- if (this -> hasVal )
96
- *this -> getPointer () = std::move (y);
54
+ if (hasVal)
55
+ *getPointer () = std::move (y);
97
56
else {
98
- OptionalTrivialStorage<T>::operator =(std::move (y));
57
+ new (storage.buffer ) T (std::move (y));
58
+ hasVal = true ;
99
59
}
100
60
return *this ;
101
61
}
102
-
103
62
OptionalStorage &operator =(OptionalStorage &&O) {
104
63
if (!O.hasVal )
105
64
reset ();
@@ -115,10 +74,11 @@ template <typename T> struct OptionalStorage : OptionalTrivialStorage<T> {
115
74
// requirements (notably: the existence of a default ctor) when implemented
116
75
// in that way. Careful SFINAE to avoid such pitfalls would be required.
117
76
OptionalStorage &operator =(const T &y) {
118
- if (this -> hasVal )
119
- *this -> getPointer () = y;
77
+ if (hasVal)
78
+ *getPointer () = y;
120
79
else {
121
- OptionalTrivialStorage<T>::operator =(y);
80
+ new (storage.buffer ) T (y);
81
+ hasVal = true ;
122
82
}
123
83
return *this ;
124
84
}
@@ -133,19 +93,26 @@ template <typename T> struct OptionalStorage : OptionalTrivialStorage<T> {
133
93
~OptionalStorage () { reset (); }
134
94
135
95
void reset () {
136
- if (this -> hasVal ) {
137
- (*this -> getPointer ()).~T ();
138
- OptionalTrivialStorage<T>:: reset () ;
96
+ if (hasVal) {
97
+ (*getPointer ()).~T ();
98
+ hasVal = false ;
139
99
}
140
100
}
101
+
102
+ T *getPointer () {
103
+ assert (hasVal);
104
+ return reinterpret_cast <T *>(storage.buffer );
105
+ }
106
+ const T *getPointer () const {
107
+ assert (hasVal);
108
+ return reinterpret_cast <const T *>(storage.buffer );
109
+ }
141
110
};
142
111
143
112
} // namespace optional_detail
144
113
145
114
template <typename T> class Optional {
146
- typename std::conditional<is_trivially_copyable<T>::value,
147
- optional_detail::OptionalTrivialStorage<T>,
148
- optional_detail::OptionalStorage<T>>::type Storage;
115
+ optional_detail::OptionalStorage<T> Storage;
149
116
150
117
public:
151
118
using value_type = T;
0 commit comments