#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
+#include <new>
#include <utility>
namespace llvm {
return *this;
}
+#if LLVM_HAS_VARIADIC_TEMPLATES
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename ...ArgTypes>
+ void emplace(ArgTypes &&...Args) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
+ }
+
+#else
+
+ /// Create a new object by default-constructing it in place.
+ void emplace() {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T();
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1>
+ void emplace(T1 &&A1) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1));
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1, typename T2>
+ void emplace(T1 &&A1, T2 &&A2) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2));
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1, typename T2, typename T3>
+ void emplace(T1 &&A1, T2 &&A2, T3 &&A3) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
+ std::forward<T3>(A3));
+ }
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template<typename T1, typename T2, typename T3, typename T4>
+ void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) {
+ reset();
+ hasVal = true;
+ new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2),
+ std::forward<T3>(A3), std::forward<T4>(A4));
+ }
+
+#endif // LLVM_HAS_VARIADIC_TEMPLATES
+
static inline Optional create(const T* y) {
return y ? Optional(*y) : Optional();
}
EXPECT_EQ(5, A.getValueOr(42));
}
+struct MultiArgConstructor {
+ int x, y;
+ MultiArgConstructor(int x, int y) : x(x), y(y) {}
+ explicit MultiArgConstructor(int x, bool positive)
+ : x(x), y(positive ? x : -x) {}
+
+ MultiArgConstructor(const MultiArgConstructor &) = delete;
+ MultiArgConstructor(MultiArgConstructor &&) = delete;
+ MultiArgConstructor &operator=(const MultiArgConstructor &) = delete;
+ MultiArgConstructor &operator=(MultiArgConstructor &&) = delete;
+
+ static unsigned Destructions;
+ ~MultiArgConstructor() {
+ ++Destructions;
+ }
+ static void ResetCounts() {
+ Destructions = 0;
+ }
+};
+unsigned MultiArgConstructor::Destructions = 0;
+
+TEST_F(OptionalTest, Emplace) {
+ MultiArgConstructor::ResetCounts();
+ Optional<MultiArgConstructor> A;
+
+ A.emplace(1, 2);
+ EXPECT_TRUE(A.hasValue());
+ EXPECT_EQ(1, A->x);
+ EXPECT_EQ(2, A->y);
+ EXPECT_EQ(0u, MultiArgConstructor::Destructions);
+
+ A.emplace(5, false);
+ EXPECT_TRUE(A.hasValue());
+ EXPECT_EQ(5, A->x);
+ EXPECT_EQ(-5, A->y);
+ EXPECT_EQ(1u, MultiArgConstructor::Destructions);
+}
+
struct MoveOnly {
static unsigned MoveConstructions;
static unsigned Destructions;
EXPECT_EQ(1u, MoveOnly::Destructions);
}
+TEST_F(OptionalTest, MoveOnlyEmplace) {
+ Optional<MoveOnly> A;
+ MoveOnly::ResetCounts();
+ A.emplace(4);
+ EXPECT_TRUE((bool)A);
+ EXPECT_EQ(4, A->val);
+ EXPECT_EQ(0u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
+}
+
#if LLVM_HAS_RVALUE_REFERENCE_THIS
TEST_F(OptionalTest, MoveGetValueOr) {