summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouis Dionne <ldionne@apple.com>2019-08-12 18:30:31 +0000
committerLouis Dionne <ldionne@apple.com>2019-08-12 18:30:31 +0000
commit1308011e1b5c5382281a63dd4191a1784f8d2295 (patch)
tree1fbf40bca77bc711b1055f6195ff6bf99277d18e
parent38a1aa117f3d1974ab6653b692e9946e3d11db4a (diff)
downloadbcm5719-llvm-1308011e1b5c5382281a63dd4191a1784f8d2295.tar.gz
bcm5719-llvm-1308011e1b5c5382281a63dd4191a1784f8d2295.zip
[libc++] Implement CTAD for std::tuple
Summary: We were using implicit deduction guides instead of explicit ones, however the implicit ones don't do work anymore when changing the constructors. This commit adds the actual guides specified in the Standard to make libc++ (1) closer to the Standard and (2) more resistent to changes in std::tuple's constructors. Reviewers: Quuxplusone Subscribers: christof, jkorous, dexonsmith, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D65225 llvm-svn: 368599
-rw-r--r--libcxx/include/tuple28
-rw-r--r--libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp (renamed from libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp)70
2 files changed, 78 insertions, 20 deletions
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 65065872991..32bc86913aa 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -69,6 +69,17 @@ public:
void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...));
};
+template <class ...T>
+tuple(T...) -> tuple<T...>; // since C++17
+template <class T1, class T2>
+tuple(pair<T1, T2>) -> tuple<T1, T2>; // since C++17
+template <class Alloc, class ...T>
+tuple(allocator_arg_t, Alloc, T...) -> tuple<T...>; // since C++17
+template <class Alloc, class T1, class T2>
+tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>; // since C++17
+template <class Alloc, class ...T>
+tuple(allocator_arg_t, Alloc, tuple<T...>) -> tuple<T...>; // since C++17
+
inline constexpr unspecified ignore;
template <class... T> tuple<V...> make_tuple(T&&...); // constexpr in C++14
@@ -943,13 +954,16 @@ public:
};
#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
-// NOTE: These are not yet standardized, but are required to simulate the
-// implicit deduction guide that should be generated had libc++ declared the
-// tuple-like constructors "correctly"
-template <class _Alloc, class ..._Args>
-tuple(allocator_arg_t, const _Alloc&, tuple<_Args...> const&) -> tuple<_Args...>;
-template <class _Alloc, class ..._Args>
-tuple(allocator_arg_t, const _Alloc&, tuple<_Args...>&&) -> tuple<_Args...>;
+template <class ..._Tp>
+tuple(_Tp...) -> tuple<_Tp...>;
+template <class _Tp1, class _Tp2>
+tuple(pair<_Tp1, _Tp2>) -> tuple<_Tp1, _Tp2>;
+template <class _Alloc, class ..._Tp>
+tuple(allocator_arg_t, _Alloc, _Tp...) -> tuple<_Tp...>;
+template <class _Alloc, class _Tp1, class _Tp2>
+tuple(allocator_arg_t, _Alloc, pair<_Tp1, _Tp2>) -> tuple<_Tp1, _Tp2>;
+template <class _Alloc, class ..._Tp>
+tuple(allocator_arg_t, _Alloc, tuple<_Tp...>) -> tuple<_Tp...>;
#endif
template <class ..._Tp>
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp
index 3ff089a0b31..e903cd0b476 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/implicit_deduction_guides.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/deduct.pass.cpp
@@ -33,13 +33,15 @@
// using AT = std::allocator_arg_t
// ---------------
// (1) tuple(const Types&...) -> tuple<Types...>
-// (2) explicit tuple(const Types&...) -> tuple<Types...>
-// (3) tuple(AT, A const&, Types const&...) -> tuple<Types...>
-// (4) explicit tuple(AT, A const&, Types const&...) -> tuple<Types...>
-// (5) tuple(tuple const& t) -> decltype(t)
-// (6) tuple(tuple&& t) -> decltype(t)
-// (7) tuple(AT, A const&, tuple const& t) -> decltype(t)
-// (8) tuple(AT, A const&, tuple&& t) -> decltype(t)
+// (2) tuple(pair<T1, T2>) -> tuple<T1, T2>;
+// (3) explicit tuple(const Types&...) -> tuple<Types...>
+// (4) tuple(AT, A const&, Types const&...) -> tuple<Types...>
+// (5) explicit tuple(AT, A const&, Types const&...) -> tuple<Types...>
+// (6) tuple(AT, A, pair<T1, T2>) -> tuple<T1, T2>
+// (7) tuple(tuple const& t) -> decltype(t)
+// (8) tuple(tuple&& t) -> decltype(t)
+// (9) tuple(AT, A const&, tuple const& t) -> decltype(t)
+// (10) tuple(AT, A const&, tuple&& t) -> decltype(t)
void test_primary_template()
{
const std::allocator<int> A;
@@ -52,6 +54,27 @@ void test_primary_template()
ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, decltype(nullptr)>);
}
{ // Testing (2)
+ std::pair<int, char> p1(1, 'c');
+ std::tuple t1(p1);
+ ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>);
+
+ std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr));
+ std::tuple t2(p2);
+ ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>);
+
+ int i = 3;
+ std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c');
+ std::tuple t3(p3);
+ ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>);
+
+ std::pair<int&, char> p4(i, 'c');
+ std::tuple t4(p4);
+ ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>);
+
+ std::tuple t5(std::pair<int, char>(1, 'c'));
+ ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>);
+ }
+ { // Testing (3)
using T = ExplicitTestTypes::TestType;
static_assert(!std::is_convertible<T const&, T>::value, "");
@@ -62,7 +85,7 @@ void test_primary_template()
std::tuple t2(T{}, 101l, v);
ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>);
}
- { // Testing (3)
+ { // Testing (4)
int x = 101;
std::tuple t1(AT, A, 42);
ASSERT_SAME_TYPE(decltype(t1), std::tuple<int>);
@@ -70,7 +93,7 @@ void test_primary_template()
std::tuple t2(AT, A, 42, 0.0, x);
ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, double, int>);
}
- { // Testing (4)
+ { // Testing (5)
using T = ExplicitTestTypes::TestType;
static_assert(!std::is_convertible<T const&, T>::value, "");
@@ -81,26 +104,47 @@ void test_primary_template()
std::tuple t2(AT, A, T{}, 101l, v);
ASSERT_SAME_TYPE(decltype(t2), std::tuple<T, long, T>);
}
- { // Testing (5)
+ { // Testing (6)
+ std::pair<int, char> p1(1, 'c');
+ std::tuple t1(AT, A, p1);
+ ASSERT_SAME_TYPE(decltype(t1), std::tuple<int, char>);
+
+ std::pair<int, std::tuple<char, long, void*>> p2(1, std::tuple<char, long, void*>('c', 3l, nullptr));
+ std::tuple t2(AT, A, p2);
+ ASSERT_SAME_TYPE(decltype(t2), std::tuple<int, std::tuple<char, long, void*>>);
+
+ int i = 3;
+ std::pair<std::reference_wrapper<int>, char> p3(std::ref(i), 'c');
+ std::tuple t3(AT, A, p3);
+ ASSERT_SAME_TYPE(decltype(t3), std::tuple<std::reference_wrapper<int>, char>);
+
+ std::pair<int&, char> p4(i, 'c');
+ std::tuple t4(AT, A, p4);
+ ASSERT_SAME_TYPE(decltype(t4), std::tuple<int&, char>);
+
+ std::tuple t5(AT, A, std::pair<int, char>(1, 'c'));
+ ASSERT_SAME_TYPE(decltype(t5), std::tuple<int, char>);
+ }
+ { // Testing (7)
using Tup = std::tuple<int, decltype(nullptr)>;
const Tup t(42, nullptr);
std::tuple t1(t);
ASSERT_SAME_TYPE(decltype(t1), Tup);
}
- { // Testing (6)
+ { // Testing (8)
using Tup = std::tuple<void*, unsigned, char>;
std::tuple t1(Tup(nullptr, 42, 'a'));
ASSERT_SAME_TYPE(decltype(t1), Tup);
}
- { // Testing (7)
+ { // Testing (9)
using Tup = std::tuple<int, decltype(nullptr)>;
const Tup t(42, nullptr);
std::tuple t1(AT, A, t);
ASSERT_SAME_TYPE(decltype(t1), Tup);
}
- { // Testing (8)
+ { // Testing (10)
using Tup = std::tuple<void*, unsigned, char>;
std::tuple t1(AT, A, Tup(nullptr, 42, 'a'));
ASSERT_SAME_TYPE(decltype(t1), Tup);
OpenPOWER on IntegriCloud