diff options
author | Ahmed Charles <ahmedcharles@gmail.com> | 2014-03-09 11:20:17 +0000 |
---|---|---|
committer | Ahmed Charles <ahmedcharles@gmail.com> | 2014-03-09 11:20:17 +0000 |
commit | fee1963538a3148f3f31dd91dc9a2cc4ffb40a2d (patch) | |
tree | 75281c574d34b8d40496cb8e7f93de6e450d7335 | |
parent | e086782817441908f03e9f4c6fb2008ec414a23e (diff) | |
download | llvm-fee1963538a3148f3f31dd91dc9a2cc4ffb40a2d.tar.gz llvm-fee1963538a3148f3f31dd91dc9a2cc4ffb40a2d.tar.bz2 llvm-fee1963538a3148f3f31dd91dc9a2cc4ffb40a2d.tar.xz |
[C++11] Add llvm::make_unique, according to N3656.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203387 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/ADT/STLExtras.h | 169 | ||||
-rw-r--r-- | unittests/ADT/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/ADT/MakeUniqueTest.cpp | 76 |
3 files changed, 246 insertions, 0 deletions
diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index c1a619838b..5a3756de3d 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -17,10 +17,12 @@ #ifndef LLVM_ADT_STLEXTRAS_H #define LLVM_ADT_STLEXTRAS_H +#include "llvm/Support/Compiler.h" #include <cstddef> // for std::size_t #include <cstdlib> // for qsort #include <functional> #include <iterator> +#include <memory> #include <utility> // for std::pair namespace llvm { @@ -255,6 +257,173 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +//===----------------------------------------------------------------------===// +// Extra additions to <memory> +//===----------------------------------------------------------------------===// + +#if LLVM_HAS_VARIADIC_TEMPLATES + +/// Implement make_unique according to N3656. +/// +/// template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args); +/// Remarks: This function shall not participate in overload resolution unless +/// T is not an array. +/// Returns: unique_ptr<T>(new T(std::forward<Args>(args)...)). +/// +/// template<class T> unique_ptr<T> make_unique(size_t n); +/// Remarks: This function shall not participate in overload resolution unless +/// T is an array of unknown bound. +/// Returns: unique_ptr<T>(new typename remove_extent<T>::type[n]()). +/// +/// template<class T, class... Args> unspecified make_unique(Args&&...) = delete; +/// Remarks: This function shall not participate in overload resolution unless +/// T is an array of known bound. +/// +/// Use scenarios: +/// +/// Single object case: +/// +/// auto p0 = make_unique<int>(); +/// +/// auto p2 = make_unique<std::tuple<int, int>>(0, 1); +/// +/// Array case: +/// +/// auto p1 = make_unique<int[]>(2); // value-initializes the array with 0's. +/// +template <class T, class... Args> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Args &&... args) { + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + +template <class T> +typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, + std::unique_ptr<T>>::type +make_unique(size_t n) { + return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); +} + +template <class T, class... Args> +typename std::enable_if<std::extent<T>::value != 0>::type +make_unique(Args &&...) LLVM_DELETED_FUNCTION; + +#else + +template <class T> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique() { + return std::unique_ptr<T>(new T()); +} + +template <class T, class Arg1> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1) { + return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1))); +} + +template <class T, class Arg1, class Arg2> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2))); +} + +template <class T, class Arg1, class Arg2, class Arg3> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) { + return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), + std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7, class Arg8> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7), std::forward<Arg8>(arg8))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7, class Arg8, class Arg9> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7), std::forward<Arg8>(arg8), + std::forward<Arg9>(arg9))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7, class Arg8, class Arg9, class Arg10> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7), std::forward<Arg8>(arg8), + std::forward<Arg9>(arg9), std::forward<Arg10>(arg10))); +} + +template <class T> +typename std::enable_if<std::is_array<T>::value &&std::extent<T>::value == 0, + std::unique_ptr<T>>::type +make_unique(size_t n) { + return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); +} + +#endif + } // End llvm namespace #endif diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt index 66e2d20ef7..dab70b903d 100644 --- a/unittests/ADT/CMakeLists.txt +++ b/unittests/ADT/CMakeLists.txt @@ -20,6 +20,7 @@ set(ADTSources IntEqClassesTest.cpp IntervalMapTest.cpp IntrusiveRefCntPtrTest.cpp + MakeUniqueTest.cpp MapVectorTest.cpp OptionalTest.cpp OwningPtrTest.cpp diff --git a/unittests/ADT/MakeUniqueTest.cpp b/unittests/ADT/MakeUniqueTest.cpp new file mode 100644 index 0000000000..3b4938a2ef --- /dev/null +++ b/unittests/ADT/MakeUniqueTest.cpp @@ -0,0 +1,76 @@ +//===- llvm/unittest/ADT/MakeUniqueTest.cpp - make_unique unit tests ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "gtest/gtest.h" +#include <tuple> +using namespace llvm; + +namespace { + +TEST(MakeUniqueTest, SingleObject) { + auto p0 = make_unique<int>(); + EXPECT_TRUE((bool)p0); + EXPECT_EQ(0, *p0); + + auto p1 = make_unique<int>(5); + EXPECT_TRUE((bool)p1); + EXPECT_EQ(5, *p1); + + auto p2 = make_unique<std::tuple<int, int>>(0, 1); + EXPECT_TRUE((bool)p2); + EXPECT_EQ(std::make_tuple(0, 1), *p2); + + auto p3 = make_unique<std::tuple<int, int, int>>(0, 1, 2); + EXPECT_TRUE((bool)p3); + EXPECT_EQ(std::make_tuple(0, 1, 2), *p3); + + auto p4 = make_unique<std::tuple<int, int, int, int>>(0, 1, 2, 3); + EXPECT_TRUE((bool)p4); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3), *p4); + + auto p5 = make_unique<std::tuple<int, int, int, int, int>>(0, 1, 2, 3, 4); + EXPECT_TRUE((bool)p5); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4), *p5); + + auto p6 = + make_unique<std::tuple<int, int, int, int, int, int>>(0, 1, 2, 3, 4, 5); + EXPECT_TRUE((bool)p6); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5), *p6); + + auto p7 = make_unique<std::tuple<int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6); + EXPECT_TRUE((bool)p7); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6), *p7); + + auto p8 = make_unique<std::tuple<int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7); + EXPECT_TRUE((bool)p8); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7), *p8); + + auto p9 = + make_unique<std::tuple<int, int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7, 8); + EXPECT_TRUE((bool)p9); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8), *p9); + + auto p10 = + make_unique<std::tuple<int, int, int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + EXPECT_TRUE((bool)p10); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), *p10); +} + +TEST(MakeUniqueTest, Array) { + auto p1 = make_unique<int[]>(2); + EXPECT_TRUE((bool)p1); + EXPECT_EQ(0, p1[0]); + EXPECT_EQ(0, p1[1]); +} +} |