summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/utilities/tuple
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2017-01-04 22:38:46 +0000
committerEric Fiselier <eric@efcs.ca>2017-01-04 22:38:46 +0000
commitcb0d4df97490ec2d2b1cdf7574d26b1bc4063599 (patch)
treefd4068a1365b0db24e75a05549721732569b05ee /libcxx/test/std/utilities/tuple
parentb44f0bfb3a14fa757f49cba64cf452a2eee969b9 (diff)
downloadbcm5719-llvm-cb0d4df97490ec2d2b1cdf7574d26b1bc4063599.tar.gz
bcm5719-llvm-cb0d4df97490ec2d2b1cdf7574d26b1bc4063599.zip
[libcxx] Re-implement LWG 2770 again: Fix tuple_size to work with structured bindings
Summary: This patch attempts to re-implement a fix for LWG 2770, but not the actual specified PR. The PR for 2770 specifies tuple_size<T const> as only conditionally providing a `::value` member. However C++17 structured bindings require `tuple_size<T const>` to be complete only if `tuple_size<T>` is also complete. Therefore this patch implements only provides the specialization `tuple_size<T CV>` iff `tuple_size<T>` is a complete type. This fixes http://llvm.org/PR31513. Reviewers: mclow.lists, rsmith, mpark Subscribers: mpark, cfe-commits Differential Revision: https://reviews.llvm.org/D28222 llvm-svn: 291019
Diffstat (limited to 'libcxx/test/std/utilities/tuple')
-rw-r--r--libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp18
-rw-r--r--libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.fail.cpp63
-rw-r--r--libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp67
-rw-r--r--libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp138
-rw-r--r--libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp39
5 files changed, 307 insertions, 18 deletions
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp
index 3e4145c79cb..49b4215a195 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp
@@ -20,13 +20,6 @@
#include <tuple>
#include <type_traits>
-template <class T, class = decltype(std::tuple_size<T>::value)>
-constexpr bool has_value(int) { return true; }
-template <class> constexpr bool has_value(long) { return false; }
-template <class T> constexpr bool has_value() { return has_value<T>(0); }
-
-struct Dummy {};
-
template <class T, std::size_t N>
void test()
{
@@ -40,21 +33,10 @@ void test()
std::tuple_size<const volatile T> >::value), "");
}
-void test_tuple_size_value_sfinae() {
- // Test that the ::value member does not exist
- static_assert(has_value<std::tuple<int> const>(), "");
- static_assert(has_value<std::pair<int, long> volatile>(), "");
- static_assert(!has_value<int>(), "");
- static_assert(!has_value<const int>(), "");
- static_assert(!has_value<volatile void>(), "");
- static_assert(!has_value<const volatile std::tuple<int>&>(), "");
-}
-
int main()
{
test<std::tuple<>, 0>();
test<std::tuple<int>, 1>();
test<std::tuple<char, int>, 2>();
test<std::tuple<char, char*, int>, 3>();
- test_tuple_size_value_sfinae();
}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.fail.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.fail.cpp
new file mode 100644
index 00000000000..2e807e35b9e
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.fail.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <class... Types>
+// class tuple_size<tuple<Types...>>
+// : public integral_constant<size_t, sizeof...(Types)> { };
+
+// UNSUPPORTED: c++98, c++03
+
+#include <tuple>
+#include <array>
+#include <type_traits>
+
+struct Dummy1 {};
+struct Dummy2 {};
+struct Dummy3 {};
+
+template <>
+class std::tuple_size<Dummy1> {
+public:
+ static size_t value;
+};
+
+template <>
+class std::tuple_size<Dummy2> {
+public:
+ static void value() {}
+};
+
+template <>
+class std::tuple_size<Dummy3> {};
+
+int main()
+{
+ // Test that tuple_size<const T> is not incomplete when tuple_size<T>::value
+ // is well-formed but not a constant expression.
+ {
+ // expected-error@__tuple:* 1 {{is not a constant expression}}
+ (void)std::tuple_size<const Dummy1>::value; // expected-note {{here}}
+ }
+ // Test that tuple_size<const T> is not incomplete when tuple_size<T>::value
+ // is well-formed but not convertible to size_t.
+ {
+ // expected-error@__tuple:* 1 {{value of type 'void ()' is not implicitly convertible to 'unsigned long'}}
+ (void)std::tuple_size<const Dummy2>::value; // expected-note {{here}}
+ }
+ // Test that tuple_size<const T> generates an error when tuple_size<T> is
+ // complete but ::value isn't a constant expression convertible to size_t.
+ {
+ // expected-error@__tuple:* 1 {{no member named 'value'}}
+ (void)std::tuple_size<const Dummy3>::value; // expected-note {{here}}
+ }
+}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp
new file mode 100644
index 00000000000..ccdd48e4c11
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <class... Types>
+// class tuple_size<tuple<Types...>>
+// : public integral_constant<size_t, sizeof...(Types)> { };
+
+// XFAIL: gcc-4.9
+// UNSUPPORTED: c++98, c++03
+
+#include <tuple>
+#include <array>
+#include <type_traits>
+
+template <class T, size_t Size = sizeof(std::tuple_size<T>)>
+constexpr bool is_complete(int) { static_assert(Size > 0, ""); return true; }
+template <class> constexpr bool is_complete(long) { return false; }
+template <class T> constexpr bool is_complete() { return is_complete<T>(0); }
+
+struct Dummy1 {};
+struct Dummy2 {};
+
+namespace std {
+template <> class tuple_size<Dummy1> : public integral_constant<size_t, 0> {};
+}
+
+template <class T>
+void test_complete() {
+ static_assert(is_complete<T>(), "");
+ static_assert(is_complete<const T>(), "");
+ static_assert(is_complete<volatile T>(), "");
+ static_assert(is_complete<const volatile T>(), "");
+}
+
+template <class T>
+void test_incomplete() {
+ static_assert(!is_complete<T>(), "");
+ static_assert(!is_complete<const T>(), "");
+ static_assert(!is_complete<volatile T>(), "");
+ static_assert(!is_complete<const volatile T>(), "");
+}
+
+
+int main()
+{
+ test_complete<std::tuple<> >();
+ test_complete<std::tuple<int&> >();
+ test_complete<std::tuple<int&&, int&, void*>>();
+ test_complete<std::pair<int, long> >();
+ test_complete<std::array<int, 5> >();
+ test_complete<Dummy1>();
+
+ test_incomplete<void>();
+ test_incomplete<int>();
+ test_incomplete<std::tuple<int>&>();
+ test_incomplete<Dummy2>();
+}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp
new file mode 100644
index 00000000000..742b00aea71
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp
@@ -0,0 +1,138 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <class... Types>
+// class tuple_size<tuple<Types...>>
+// : public integral_constant<size_t, sizeof...(Types)> { };
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// XFAIL: libcpp-no-structured-bindings
+
+#include <tuple>
+#include <array>
+#include <type_traits>
+#include <cassert>
+
+struct S { int x; };
+
+void test_decomp_user_type() {
+ {
+ S s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &s.x);
+ }
+ {
+ S const s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &s.x);
+ }
+}
+
+void test_decomp_tuple() {
+ typedef std::tuple<int> T;
+ {
+ T s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+ {
+ T const s{99};
+ auto [m1] = s;
+ auto& [r1] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+}
+
+
+void test_decomp_pair() {
+ typedef std::pair<int, double> T;
+ {
+ T s{99, 42.1};
+ auto [m1, m2] = s;
+ auto& [r1, r2] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+ {
+ T const s{99, 42.1};
+ auto [m1, m2] = s;
+ auto& [r1, r2] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+}
+
+void test_decomp_array() {
+ typedef std::array<int, 3> T;
+ {
+ T s{{99, 42, -1}};
+ auto [m1, m2, m3] = s;
+ auto& [r1, r2, r3] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+ {
+ T const s{{99, 42, -1}};
+ auto [m1, m2, m3] = s;
+ auto& [r1, r2, r3] = s;
+ assert(m1 == 99);
+ assert(&r1 == &std::get<0>(s));
+ }
+}
+
+struct Test {
+ int x;
+};
+
+template <size_t N>
+int get(Test const&) { static_assert(N == 0, ""); return -1; }
+
+template <>
+class std::tuple_element<0, Test> {
+public:
+ typedef int type;
+};
+
+void test_before_tuple_size_specialization() {
+ Test const t{99};
+ auto& [p] = t;
+ assert(p == 99);
+}
+
+template <>
+class std::tuple_size<Test> {
+public:
+ static const size_t value = 1;
+};
+
+void test_after_tuple_size_specialization() {
+ Test const t{99};
+ auto& [p] = t;
+ assert(p == -1);
+}
+
+int main() {
+ test_decomp_user_type();
+ test_decomp_tuple();
+ test_decomp_pair();
+ test_decomp_array();
+ test_before_tuple_size_specialization();
+ test_after_tuple_size_specialization();
+}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp
new file mode 100644
index 00000000000..31ebe587837
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// template <class... Types> class tuple;
+
+// template <class... Types>
+// class tuple_size<tuple<Types...>>
+// : public integral_constant<size_t, sizeof...(Types)> { };
+
+// XFAIL: gcc-4.9
+// UNSUPPORTED: c++98, c++03
+
+#include <tuple>
+#include <type_traits>
+
+template <class T, class = decltype(std::tuple_size<T>::value)>
+constexpr bool has_value(int) { return true; }
+template <class> constexpr bool has_value(long) { return false; }
+template <class T> constexpr bool has_value() { return has_value<T>(0); }
+
+struct Dummy {};
+
+int main() {
+ // Test that the ::value member does not exist
+ static_assert(has_value<std::tuple<int> const>(), "");
+ static_assert(has_value<std::pair<int, long> volatile>(), "");
+ static_assert(!has_value<int>(), "");
+ static_assert(!has_value<const int>(), "");
+ static_assert(!has_value<volatile void>(), "");
+ static_assert(!has_value<const volatile std::tuple<int>&>(), "");
+}
OpenPOWER on IntegriCloud