llvm.org GIT mirror llvm / ea72255
Add move ctor/assignment to Optional<T> Code review feedback for r175580 by Jordan Rose. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175729 91177308-0d34-0410-b5e6-96231b3b80d8 David Blaikie 6 years ago
2 changed file(s) with 138 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
4545 Optional(T &&y) : hasVal(true) {
4646 new (storage.buffer) T(std::forward(y));
4747 }
48 Optional(Optional &&O) : hasVal(O) {
49 if (O) {
50 new (storage.buffer) T(std::move(*O));
51 O.reset();
52 }
53 }
54 Optional &operator=(T &&y) {
55 if (hasVal)
56 **this = std::move(y);
57 else {
58 new (storage.buffer) T(std::move(y));
59 hasVal = true;
60 }
61 return *this;
62 }
63 Optional &operator=(Optional &&O) {
64 if (!O)
65 reset();
66 else {
67 *this = std::move(*O);
68 O.reset();
69 }
70 return *this;
71 }
4872 #endif
4973
5074 static inline Optional create(const T* y) {
5175 return y ? Optional(*y) : Optional();
5276 }
5377
78 // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
79 // could be made more efficient by passing by value, possibly unifying them
80 // with the rvalue versions above - but this could place a different set of
81 // requirements (notably: the existence of a default ctor) when implemented
82 // in that way. Careful SFINAE to avoid such pitfalls would be required.
5483 Optional &operator=(const T &y) {
5584 if (hasVal)
5685 **this = y;
3939 unsigned NonDefaultConstructible::Destructions = 0;
4040 unsigned NonDefaultConstructible::CopyAssignments = 0;
4141
42 struct MoveOnly {
43 static unsigned MoveConstructions;
44 static unsigned Destructions;
45 static unsigned MoveAssignments;
46 int val;
47 explicit MoveOnly(int val) : val(val) {
48 }
49 MoveOnly(MoveOnly&& other) {
50 val = other.val;
51 ++MoveConstructions;
52 }
53 MoveOnly &operator=(MoveOnly&& other) {
54 val = other.val;
55 ++MoveAssignments;
56 return *this;
57 }
58 ~MoveOnly() {
59 ++Destructions;
60 }
61 static void ResetCounts() {
62 MoveConstructions = 0;
63 Destructions = 0;
64 MoveAssignments = 0;
65 }
66 };
67
68 unsigned MoveOnly::MoveConstructions = 0;
69 unsigned MoveOnly::Destructions = 0;
70 unsigned MoveOnly::MoveAssignments = 0;
71
4272 // Test fixture
4373 class OptionalTest : public testing::Test {
4474 };
168198 EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
169199 }
170200
201 TEST_F(OptionalTest, MoveOnlyNull) {
202 MoveOnly::ResetCounts();
203 Optional O;
204 EXPECT_EQ(0u, MoveOnly::MoveConstructions);
205 EXPECT_EQ(0u, MoveOnly::MoveAssignments);
206 EXPECT_EQ(0u, MoveOnly::Destructions);
207 }
208
209 TEST_F(OptionalTest, MoveOnlyConstruction) {
210 MoveOnly::ResetCounts();
211 Optional O(MoveOnly(3));
212 EXPECT_TRUE((bool)O);
213 EXPECT_EQ(3, O->val);
214 EXPECT_EQ(1u, MoveOnly::MoveConstructions);
215 EXPECT_EQ(0u, MoveOnly::MoveAssignments);
216 EXPECT_EQ(1u, MoveOnly::Destructions);
217 }
218
219 TEST_F(OptionalTest, MoveOnlyMoveConstruction) {
220 Optional A(MoveOnly(3));
221 MoveOnly::ResetCounts();
222 Optional B(std::move(A));
223 EXPECT_FALSE((bool)A);
224 EXPECT_TRUE((bool)B);
225 EXPECT_EQ(3, B->val);
226 EXPECT_EQ(1u, MoveOnly::MoveConstructions);
227 EXPECT_EQ(0u, MoveOnly::MoveAssignments);
228 EXPECT_EQ(1u, MoveOnly::Destructions);
229 }
230
231 TEST_F(OptionalTest, MoveOnlyAssignment) {
232 MoveOnly::ResetCounts();
233 Optional O;
234 O = MoveOnly(3);
235 EXPECT_TRUE((bool)O);
236 EXPECT_EQ(3, O->val);
237 EXPECT_EQ(1u, MoveOnly::MoveConstructions);
238 EXPECT_EQ(0u, MoveOnly::MoveAssignments);
239 EXPECT_EQ(1u, MoveOnly::Destructions);
240 }
241
242 TEST_F(OptionalTest, MoveOnlyInitializingAssignment) {
243 Optional A(MoveOnly(3));
244 Optional B;
245 MoveOnly::ResetCounts();
246 B = std::move(A);
247 EXPECT_FALSE((bool)A);
248 EXPECT_TRUE((bool)B);
249 EXPECT_EQ(3, B->val);
250 EXPECT_EQ(1u, MoveOnly::MoveConstructions);
251 EXPECT_EQ(0u, MoveOnly::MoveAssignments);
252 EXPECT_EQ(1u, MoveOnly::Destructions);
253 }
254
255 TEST_F(OptionalTest, MoveOnlyNullingAssignment) {
256 Optional A;
257 Optional B(MoveOnly(3));
258 MoveOnly::ResetCounts();
259 B = std::move(A);
260 EXPECT_FALSE((bool)A);
261 EXPECT_FALSE((bool)B);
262 EXPECT_EQ(0u, MoveOnly::MoveConstructions);
263 EXPECT_EQ(0u, MoveOnly::MoveAssignments);
264 EXPECT_EQ(1u, MoveOnly::Destructions);
265 }
266
267 TEST_F(OptionalTest, MoveOnlyAssigningAssignment) {
268 Optional A(MoveOnly(3));
269 Optional B(MoveOnly(4));
270 MoveOnly::ResetCounts();
271 B = std::move(A);
272 EXPECT_FALSE((bool)A);
273 EXPECT_TRUE((bool)B);
274 EXPECT_EQ(3, B->val);
275 EXPECT_EQ(0u, MoveOnly::MoveConstructions);
276 EXPECT_EQ(1u, MoveOnly::MoveAssignments);
277 EXPECT_EQ(1u, MoveOnly::Destructions);
278 }
279
171280 } // end anonymous namespace
172281