1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* A class for lazily constructing an object without sticking it on the heap. */
9 #ifndef mozilla_Maybe_h
10 #define mozilla_Maybe_h
12 #include "mozilla/Alignment.h"
13 #include "mozilla/Assertions.h"
21 * Small utility for lazily constructing objects without using dynamic storage.
22 * When a Maybe<T> is constructed, it is |empty()|, i.e., no value of T has
23 * been constructed and no T destructor will be called when the Maybe<T> is
24 * destroyed. Upon calling |construct|, a T object will be constructed with the
25 * given arguments and that object will be destroyed when the owning Maybe<T>
28 * N.B. GCC seems to miss some optimizations with Maybe and may generate extra
29 * branches/loads/stores. Use with caution on hot paths.
34 AlignedStorage2
<T
> storage
;
37 T
& asT() { return *storage
.addr(); }
40 Maybe() { constructed
= false; }
41 ~Maybe() { if (constructed
) asT().~T(); }
43 bool empty() const { return !constructed
; }
46 MOZ_ASSERT(!constructed
);
47 ::new (storage
.addr()) T();
52 void construct(const T1
& t1
) {
53 MOZ_ASSERT(!constructed
);
54 ::new (storage
.addr()) T(t1
);
58 template<class T1
, class T2
>
59 void construct(const T1
& t1
, const T2
& t2
) {
60 MOZ_ASSERT(!constructed
);
61 ::new (storage
.addr()) T(t1
, t2
);
65 template<class T1
, class T2
, class T3
>
66 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
) {
67 MOZ_ASSERT(!constructed
);
68 ::new (storage
.addr()) T(t1
, t2
, t3
);
72 template<class T1
, class T2
, class T3
, class T4
>
73 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
, const T4
& t4
) {
74 MOZ_ASSERT(!constructed
);
75 ::new (storage
.addr()) T(t1
, t2
, t3
, t4
);
79 template<class T1
, class T2
, class T3
, class T4
, class T5
>
80 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
, const T4
& t4
, const T5
& t5
) {
81 MOZ_ASSERT(!constructed
);
82 ::new (storage
.addr()) T(t1
, t2
, t3
, t4
, t5
);
86 template<class T1
, class T2
, class T3
, class T4
, class T5
,
88 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
, const T4
& t4
, const T5
& t5
,
90 MOZ_ASSERT(!constructed
);
91 ::new (storage
.addr()) T(t1
, t2
, t3
, t4
, t5
, t6
);
95 template<class T1
, class T2
, class T3
, class T4
, class T5
,
97 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
, const T4
& t4
, const T5
& t5
,
98 const T6
& t6
, const T7
& t7
) {
99 MOZ_ASSERT(!constructed
);
100 ::new (storage
.addr()) T(t1
, t2
, t3
, t4
, t5
, t6
, t7
);
104 template<class T1
, class T2
, class T3
, class T4
, class T5
,
105 class T6
, class T7
, class T8
>
106 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
, const T4
& t4
, const T5
& t5
,
107 const T6
& t6
, const T7
& t7
, const T8
& t8
) {
108 MOZ_ASSERT(!constructed
);
109 ::new (storage
.addr()) T(t1
, t2
, t3
, t4
, t5
, t6
, t7
, t8
);
113 template<class T1
, class T2
, class T3
, class T4
, class T5
,
114 class T6
, class T7
, class T8
, class T9
>
115 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
, const T4
& t4
, const T5
& t5
,
116 const T6
& t6
, const T7
& t7
, const T8
& t8
, const T9
& t9
) {
117 MOZ_ASSERT(!constructed
);
118 ::new (storage
.addr()) T(t1
, t2
, t3
, t4
, t5
, t6
, t7
, t8
, t9
);
122 template<class T1
, class T2
, class T3
, class T4
, class T5
,
123 class T6
, class T7
, class T8
, class T9
, class T10
>
124 void construct(const T1
& t1
, const T2
& t2
, const T3
& t3
, const T4
& t4
, const T5
& t5
,
125 const T6
& t6
, const T7
& t7
, const T8
& t8
, const T9
& t9
, const T10
& t10
) {
126 MOZ_ASSERT(!constructed
);
127 ::new (storage
.addr()) T(t1
, t2
, t3
, t4
, t5
, t6
, t7
, t8
, t9
, t10
);
132 MOZ_ASSERT(constructed
);
137 MOZ_ASSERT(constructed
);
141 const T
& ref() const {
142 MOZ_ASSERT(constructed
);
143 return const_cast<Maybe
*>(this)->asT();
151 void destroyIfConstructed() {
157 Maybe(const Maybe
& other
) MOZ_DELETE
;
158 const Maybe
& operator=(const Maybe
& other
) MOZ_DELETE
;
161 } // namespace mozilla
163 #endif /* mozilla_Maybe_h */