Index: include/llvm/ADT/Optional.h =================================================================== --- include/llvm/ADT/Optional.h +++ include/llvm/ADT/Optional.h @@ -20,6 +20,7 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include +#include #include namespace llvm { @@ -69,6 +70,18 @@ return *this; } +#if LLVM_HAS_VARIADIC_TEMPLATES + + /// Create a new object by constructing it in place with the given arguments. + template + void emplace(ArgTypes &&...Args) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward(Args)...); + } + +#endif // LLVM_HAS_VARIADIC_TEMPLATES + static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } Index: unittests/ADT/OptionalTest.cpp =================================================================== --- unittests/ADT/OptionalTest.cpp +++ unittests/ADT/OptionalTest.cpp @@ -177,6 +177,25 @@ EXPECT_EQ(5, A.getValueOr(42)); } + +#if LLVM_HAS_VARIADIC_TEMPLATES + +struct MultiArgConstructor { + int x, y; + MultiArgConstructor(int x, int y) : x(x), y(y) {} +}; + +TEST_F(OptionalTest, Emplace) { + Optional A; + A.emplace(1, 2); + EXPECT_TRUE(A.hasValue()); + EXPECT_EQ(1, A->x); + EXPECT_EQ(2, A->y); +} + +#endif // LLVM_HAS_VARIADIC_TEMPLATES + + struct MoveOnly { static unsigned MoveConstructions; static unsigned Destructions; @@ -286,6 +305,21 @@ EXPECT_EQ(1u, MoveOnly::Destructions); } +#if LLVM_HAS_VARIADIC_TEMPLATES + +TEST_F(OptionalTest, MoveOnlyEmplace) { + Optional 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); +} + +#endif // LLVM_HAS_VARIADIC_TEMPLATES + #if LLVM_HAS_RVALUE_REFERENCE_THIS TEST_F(OptionalTest, MoveGetValueOr) {