summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/experimental/utilities/tuple/tuple.apply
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/test/std/experimental/utilities/tuple/tuple.apply')
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/arg_type.pass.cpp182
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp118
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/extended_types.pass.cpp423
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/large_arity.pass.cpp146
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp50
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/return_type.pass.cpp76
-rw-r--r--libcxx/test/std/experimental/utilities/tuple/tuple.apply/types.pass.cpp427
7 files changed, 1422 insertions, 0 deletions
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/arg_type.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/arg_type.pass.cpp
new file mode 100644
index 00000000000..56dc3c6aaa2
--- /dev/null
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/arg_type.pass.cpp
@@ -0,0 +1,182 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <experimental/tuple>
+
+// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
+
+// Test with different ref/ptr/cv qualified argument types.
+
+#include <experimental/tuple>
+#include <array>
+#include <utility>
+#include <cassert>
+
+namespace ex = std::experimental;
+
+int call_with_value(int x, int y) { return (x + y); }
+int call_with_ref(int & x, int & y) { return (x + y); }
+int call_with_const_ref(int const & x, int const & y) { return (x + y); }
+int call_with_rvalue_ref(int && x, int && y) { return (x + y); }
+int call_with_pointer(int * x, int * y) { return (*x + *y); }
+int call_with_const_pointer(int const* x, int const * y) { return (*x + *y); }
+
+
+template <class Tuple>
+void test_values()
+{
+ {
+ Tuple t{1, 2};
+ assert(3 == ex::apply(call_with_value, t));
+ }
+ {
+ Tuple t{2, 2};
+ assert(4 == ex::apply(call_with_ref, t));
+ }
+ {
+ Tuple t{2, 3};
+ assert(5 == ex::apply(call_with_const_ref, t));
+ }
+ {
+ Tuple t{3, 3};
+ assert(6 == ex::apply(call_with_rvalue_ref, static_cast<Tuple &&>(t)));
+ }
+ {
+ Tuple const t{4, 4};
+ assert(8 == ex::apply(call_with_value, t));
+ }
+ {
+ Tuple const t{4, 5};
+ assert(9 == ex::apply(call_with_const_ref, t));
+ }
+}
+
+template <class Tuple>
+void test_refs()
+{
+ int x = 0;
+ int y = 0;
+ {
+ x = 1; y = 2;
+ Tuple t{x, y};
+ assert(3 == ex::apply(call_with_value, t));
+ }
+ {
+ x = 2; y = 2;
+ Tuple t{x, y};
+ assert(4 == ex::apply(call_with_ref, t));
+ }
+ {
+ x = 2; y = 3;
+ Tuple t{x, y};
+ assert(5 == ex::apply(call_with_const_ref, t));
+ }
+ {
+ x = 3; y = 3;
+ Tuple const t{x, y};
+ assert(6 == ex::apply(call_with_value, t));
+ }
+ {
+ x = 3; y = 4;
+ Tuple const t{x, y};
+ assert(7 == ex::apply(call_with_const_ref, t));
+ }
+}
+
+template <class Tuple>
+void test_const_refs()
+{
+ int x = 0;
+ int y = 0;
+ {
+ x = 1; y = 2;
+ Tuple t{x, y};
+ assert(3 == ex::apply(call_with_value, t));
+ }
+ {
+ x = 2; y = 3;
+ Tuple t{x, y};
+ assert(5 == ex::apply(call_with_const_ref, t));
+ }
+ {
+ x = 3; y = 3;
+ Tuple const t{x, y};
+ assert(6 == ex::apply(call_with_value, t));
+ }
+ {
+ x = 3; y = 4;
+ Tuple const t{x, y};
+ assert(7 == ex::apply(call_with_const_ref, t));
+ }
+}
+
+
+template <class Tuple>
+void test_pointer()
+{
+ int x = 0;
+ int y = 0;
+ {
+ x = 2; y = 2;
+ Tuple t{&x, &y};
+ assert(4 == ex::apply(call_with_pointer, t));
+ }
+ {
+ x = 2; y = 3;
+ Tuple t{&x, &y};
+ assert(5 == ex::apply(call_with_const_pointer, t));
+ }
+ {
+ x = 3; y = 4;
+ Tuple const t{&x, &y};
+ assert(7 == ex::apply(call_with_const_pointer, t));
+ }
+}
+
+
+template <class Tuple>
+void test_const_pointer()
+{
+ int x = 0;
+ int y = 0;
+ {
+ x = 2; y = 3;
+ Tuple t{&x, &y};
+ assert(5 == ex::apply(call_with_const_pointer, t));
+ }
+ {
+ x = 3; y = 4;
+ Tuple const t{&x, &y};
+ assert(7 == ex::apply(call_with_const_pointer, t));
+ }
+}
+
+
+int main()
+{
+ test_values<std::tuple<int, int>>();
+ test_values<std::pair<int, int>>();
+ test_values<std::array<int, 2>>();
+
+ test_refs<std::tuple<int &, int &>>();
+ test_refs<std::pair<int &, int &>>();
+
+ test_const_refs<std::tuple<int const &, int const &>>();
+ test_const_refs<std::pair<int const &, int const &>>();
+
+ test_pointer<std::tuple<int *, int *>>();
+ test_pointer<std::pair<int *, int *>>();
+ test_pointer<std::array<int *, 2>>();
+
+ test_const_pointer<std::tuple<int const *, int const *>>();
+ test_const_pointer<std::pair<int const *, int const *>>();
+ test_const_pointer<std::array<int const *, 2>>();
+}
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
new file mode 100644
index 00000000000..5b8a8f09d1e
--- /dev/null
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/constexpr_types.pass.cpp
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <experimental/tuple>
+
+// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
+
+// Testing constexpr evaluation
+
+#include <experimental/tuple>
+#include <utility>
+#include <cassert>
+
+constexpr int f_int_0() { return 1; }
+constexpr int f_int_1(int x) { return x; }
+constexpr int f_int_2(int x, int y) { return (x + y); }
+
+struct A_int_0
+{
+ constexpr A_int_0() {}
+ constexpr int operator()() const { return 1; }
+};
+
+struct A_int_1
+{
+ constexpr A_int_1() {}
+ constexpr int operator()(int x) const { return x; }
+};
+
+struct A_int_2
+{
+ constexpr A_int_2() {}
+ constexpr int operator()(int x, int y) const { return (x + y); }
+};
+
+namespace ex = std::experimental;
+
+template <class Tuple>
+void test_0()
+{
+ // function
+ {
+ constexpr Tuple t{};
+ static_assert(1 == ex::apply(f_int_0, t), "");
+ }
+ // function pointer
+ {
+ constexpr Tuple t{};
+ constexpr auto fp = &f_int_0;
+ static_assert(1 == ex::apply(fp, t), "");
+ }
+ // functor
+ {
+ constexpr Tuple t{};
+ constexpr A_int_0 a;
+ static_assert(1 == ex::apply(a, t), "");
+ }
+}
+
+template <class Tuple>
+void test_1()
+{
+ // function
+ {
+ constexpr Tuple t{1};
+ static_assert(1 == ex::apply(f_int_1, t), "");
+ }
+ // function pointer
+ {
+ constexpr Tuple t{2};
+ constexpr int (*fp)(int) = f_int_1;
+ static_assert(2 == ex::apply(fp, t), "");
+ }
+ // functor
+ {
+ constexpr Tuple t{3};
+ constexpr A_int_1 fn;
+ static_assert(3 == ex::apply(fn, t), "");
+ }
+}
+
+template <class Tuple>
+void test_2()
+{
+ // function
+ {
+ constexpr Tuple t{1, 2};
+ static_assert(3 == ex::apply(f_int_2, t), "");
+ }
+ // function pointer
+ {
+ constexpr Tuple t{2, 3};
+ constexpr auto fp = &f_int_2;
+ static_assert(5 == ex::apply(fp, t), "");
+ }
+ // functor
+ {
+ constexpr Tuple t{3, 4};
+ constexpr A_int_2 a;
+ static_assert(7 == ex::apply(a, t), "");
+ }
+}
+
+int main()
+{
+ test_0<std::tuple<>>();
+ test_1<std::tuple<int>>();
+ test_2<std::tuple<int, int>>();
+ test_2<std::pair<int, int>>();
+}
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/extended_types.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/extended_types.pass.cpp
new file mode 100644
index 00000000000..322554925d3
--- /dev/null
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/extended_types.pass.cpp
@@ -0,0 +1,423 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <experimental/tuple>
+
+// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
+
+// Testing extended function types. The extented function types are those
+// named by INVOKE but that are not actual callable objects. These include
+// bullets 1-4 of invoke.
+
+#include <experimental/tuple>
+#include <array>
+#include <utility>
+#include <cassert>
+
+int count = 0;
+
+struct A_int_0
+{
+ A_int_0() : obj1(0){}
+ A_int_0(int x) : obj1(x) {}
+ int mem1() { return ++count; }
+ int mem2() const { return ++count; }
+ int const obj1;
+};
+
+struct A_int_1
+{
+ A_int_1() {}
+ A_int_1(int) {}
+ int mem1(int x) { return count += x; }
+ int mem2(int x) const { return count += x; }
+};
+
+struct A_int_2
+{
+ A_int_2() {}
+ A_int_2(int) {}
+ int mem1(int x, int y) { return count += (x + y); }
+ int mem2(int x, int y) const { return count += (x + y); }
+};
+
+template <class A>
+struct A_wrap
+{
+ A_wrap() {}
+ A_wrap(int x) : m_a(x) {}
+ A & operator*() { return m_a; }
+ A const & operator*() const { return m_a; }
+ A m_a;
+};
+
+typedef A_wrap<A_int_0> A_wrap_0;
+typedef A_wrap<A_int_1> A_wrap_1;
+typedef A_wrap<A_int_2> A_wrap_2;
+
+
+template <class A>
+struct A_base : public A
+{
+ A_base() : A() {}
+ A_base(int x) : A(x) {}
+};
+
+typedef A_base<A_int_0> A_base_0;
+typedef A_base<A_int_1> A_base_1;
+typedef A_base<A_int_2> A_base_2;
+
+namespace ex = std::experimental;
+
+template <
+ class Tuple, class ConstTuple
+ , class TuplePtr, class ConstTuplePtr
+ , class TupleWrap, class ConstTupleWrap
+ , class TupleBase, class ConstTupleBase
+ >
+void test_ext_int_0()
+{
+ count = 0;
+ typedef A_int_0 T;
+ typedef A_wrap_0 Wrap;
+ typedef A_base_0 Base;
+
+ typedef int(T::*mem1_t)();
+ mem1_t mem1 = &T::mem1;
+
+ typedef int(T::*mem2_t)() const;
+ mem2_t mem2 = &T::mem2;
+
+ typedef int const T::*obj1_t;
+ obj1_t obj1 = &T::obj1;
+
+ // member function w/ref
+ {
+ T a;
+ Tuple t{a};
+ assert(1 == ex::apply(mem1, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // member function w/pointer
+ {
+ T a;
+ TuplePtr t{&a};
+ assert(1 == ex::apply(mem1, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // member function w/base
+ {
+ Base a;
+ TupleBase t{a};
+ assert(1 == ex::apply(mem1, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // member function w/wrap
+ {
+ Wrap a;
+ TupleWrap t{a};
+ assert(1 == ex::apply(mem1, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // const member function w/ref
+ {
+ T const a;
+ ConstTuple t{a};
+ assert(1 == ex::apply(mem2, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // const member function w/pointer
+ {
+ T const a;
+ ConstTuplePtr t{&a};
+ assert(1 == ex::apply(mem2, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // const member function w/base
+ {
+ Base const a;
+ ConstTupleBase t{a};
+ assert(1 == ex::apply(mem2, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // const member function w/wrapper
+ {
+ Wrap const a;
+ ConstTupleWrap t{a};
+ assert(1 == ex::apply(mem2, t));
+ assert(1 == count);
+ }
+ // member object w/ref
+ {
+ T a{42};
+ Tuple t{a};
+ assert(42 == ex::apply(obj1, t));
+ }
+ // member object w/pointer
+ {
+ T a{42};
+ TuplePtr t{&a};
+ assert(42 == ex::apply(obj1, t));
+ }
+ // member object w/base
+ {
+ Base a{42};
+ TupleBase t{a};
+ assert(42 == ex::apply(obj1, t));
+ }
+ // member object w/wrapper
+ {
+ Wrap a{42};
+ TupleWrap t{a};
+ assert(42 == ex::apply(obj1, t));
+ }
+}
+
+
+template <
+ class Tuple, class ConstTuple
+ , class TuplePtr, class ConstTuplePtr
+ , class TupleWrap, class ConstTupleWrap
+ , class TupleBase, class ConstTupleBase
+ >
+void test_ext_int_1()
+{
+ count = 0;
+ typedef A_int_1 T;
+ typedef A_wrap_1 Wrap;
+ typedef A_base_1 Base;
+
+ typedef int(T::*mem1_t)(int);
+ mem1_t mem1 = &T::mem1;
+
+ typedef int(T::*mem2_t)(int) const;
+ mem2_t mem2 = &T::mem2;
+
+ // member function w/ref
+ {
+ T a;
+ Tuple t{a, 2};
+ assert(2 == ex::apply(mem1, t));
+ assert(count == 2);
+ }
+ count = 0;
+ // member function w/pointer
+ {
+ T a;
+ TuplePtr t{&a, 3};
+ assert(3 == ex::apply(mem1, t));
+ assert(count == 3);
+ }
+ count = 0;
+ // member function w/base
+ {
+ Base a;
+ TupleBase t{a, 4};
+ assert(4 == ex::apply(mem1, t));
+ assert(count == 4);
+ }
+ count = 0;
+ // member function w/wrap
+ {
+ Wrap a;
+ TupleWrap t{a, 5};
+ assert(5 == ex::apply(mem1, t));
+ assert(count == 5);
+ }
+ count = 0;
+ // const member function w/ref
+ {
+ T const a;
+ ConstTuple t{a, 6};
+ assert(6 == ex::apply(mem2, t));
+ assert(count == 6);
+ }
+ count = 0;
+ // const member function w/pointer
+ {
+ T const a;
+ ConstTuplePtr t{&a, 7};
+ assert(7 == ex::apply(mem2, t));
+ assert(count == 7);
+ }
+ count = 0;
+ // const member function w/base
+ {
+ Base const a;
+ ConstTupleBase t{a, 8};
+ assert(8 == ex::apply(mem2, t));
+ assert(count == 8);
+ }
+ count = 0;
+ // const member function w/wrapper
+ {
+ Wrap const a;
+ ConstTupleWrap t{a, 9};
+ assert(9 == ex::apply(mem2, t));
+ assert(9 == count);
+ }
+}
+
+
+template <
+ class Tuple, class ConstTuple
+ , class TuplePtr, class ConstTuplePtr
+ , class TupleWrap, class ConstTupleWrap
+ , class TupleBase, class ConstTupleBase
+ >
+void test_ext_int_2()
+{
+ count = 0;
+ typedef A_int_2 T;
+ typedef A_wrap_2 Wrap;
+ typedef A_base_2 Base;
+
+ typedef int(T::*mem1_t)(int, int);
+ mem1_t mem1 = &T::mem1;
+
+ typedef int(T::*mem2_t)(int, int) const;
+ mem2_t mem2 = &T::mem2;
+
+ // member function w/ref
+ {
+ T a;
+ Tuple t{a, 1, 1};
+ assert(2 == ex::apply(mem1, t));
+ assert(count == 2);
+ }
+ count = 0;
+ // member function w/pointer
+ {
+ T a;
+ TuplePtr t{&a, 1, 2};
+ assert(3 == ex::apply(mem1, t));
+ assert(count == 3);
+ }
+ count = 0;
+ // member function w/base
+ {
+ Base a;
+ TupleBase t{a, 2, 2};
+ assert(4 == ex::apply(mem1, t));
+ assert(count == 4);
+ }
+ count = 0;
+ // member function w/wrap
+ {
+ Wrap a;
+ TupleWrap t{a, 2, 3};
+ assert(5 == ex::apply(mem1, t));
+ assert(count == 5);
+ }
+ count = 0;
+ // const member function w/ref
+ {
+ T const a;
+ ConstTuple t{a, 3, 3};
+ assert(6 == ex::apply(mem2, t));
+ assert(count == 6);
+ }
+ count = 0;
+ // const member function w/pointer
+ {
+ T const a;
+ ConstTuplePtr t{&a, 3, 4};
+ assert(7 == ex::apply(mem2, t));
+ assert(count == 7);
+ }
+ count = 0;
+ // const member function w/base
+ {
+ Base const a;
+ ConstTupleBase t{a, 4, 4};
+ assert(8 == ex::apply(mem2, t));
+ assert(count == 8);
+ }
+ count = 0;
+ // const member function w/wrapper
+ {
+ Wrap const a;
+ ConstTupleWrap t{a, 4, 5};
+ assert(9 == ex::apply(mem2, t));
+ assert(9 == count);
+ }
+}
+
+int main()
+{
+ {
+ test_ext_int_0<
+ std::tuple<A_int_0 &>, std::tuple<A_int_0 const &>
+ , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *>
+ , std::tuple<A_wrap_0 &>, std::tuple<A_wrap_0 const &>
+ , std::tuple<A_base_0 &>, std::tuple<A_base_0 const &>
+ >();
+ test_ext_int_0<
+ std::tuple<A_int_0>, std::tuple<A_int_0 const>
+ , std::tuple<A_int_0 *>, std::tuple<A_int_0 const *>
+ , std::tuple<A_wrap_0>, std::tuple<A_wrap_0 const>
+ , std::tuple<A_base_0>, std::tuple<A_base_0 const>
+ >();
+ test_ext_int_0<
+ std::array<A_int_0, 1>, std::array<A_int_0 const, 1>
+ , std::array<A_int_0*, 1>, std::array<A_int_0 const*, 1>
+ , std::array<A_wrap_0, 1>, std::array<A_wrap_0 const, 1>
+ , std::array<A_base_0, 1>, std::array<A_base_0 const, 1>
+ >();
+ }
+ {
+ test_ext_int_1<
+ std::tuple<A_int_1 &, int>, std::tuple<A_int_1 const &, int>
+ , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int>
+ , std::tuple<A_wrap_1 &, int>, std::tuple<A_wrap_1 const &, int>
+ , std::tuple<A_base_1 &, int>, std::tuple<A_base_1 const &, int>
+ >();
+ test_ext_int_1<
+ std::tuple<A_int_1, int>, std::tuple<A_int_1 const, int>
+ , std::tuple<A_int_1 *, int>, std::tuple<A_int_1 const *, int>
+ , std::tuple<A_wrap_1, int>, std::tuple<A_wrap_1 const, int>
+ , std::tuple<A_base_1, int>, std::tuple<A_base_1 const, int>
+ >();
+ test_ext_int_1<
+ std::pair<A_int_1 &, int>, std::pair<A_int_1 const &, int>
+ , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int>
+ , std::pair<A_wrap_1 &, int>, std::pair<A_wrap_1 const &, int>
+ , std::pair<A_base_1 &, int>, std::pair<A_base_1 const &, int>
+ >();
+ test_ext_int_1<
+ std::pair<A_int_1, int>, std::pair<A_int_1 const, int>
+ , std::pair<A_int_1 *, int>, std::pair<A_int_1 const *, int>
+ , std::pair<A_wrap_1, int>, std::pair<A_wrap_1 const, int>
+ , std::pair<A_base_1, int>, std::pair<A_base_1 const, int>
+ >();
+ }
+ {
+ test_ext_int_2<
+ std::tuple<A_int_2 &, int, int>, std::tuple<A_int_2 const &, int, int>
+ , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int>
+ , std::tuple<A_wrap_2 &, int, int>, std::tuple<A_wrap_2 const &, int, int>
+ , std::tuple<A_base_2 &, int, int>, std::tuple<A_base_2 const &, int, int>
+ >();
+ test_ext_int_2<
+ std::tuple<A_int_2, int, int>, std::tuple<A_int_2 const, int, int>
+ , std::tuple<A_int_2 *, int, int>, std::tuple<A_int_2 const *, int, int>
+ , std::tuple<A_wrap_2, int, int>, std::tuple<A_wrap_2 const, int, int>
+ , std::tuple<A_base_2, int, int>, std::tuple<A_base_2 const, int, int>
+ >();
+ }
+}
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/large_arity.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/large_arity.pass.cpp
new file mode 100644
index 00000000000..027258ad8d1
--- /dev/null
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/large_arity.pass.cpp
@@ -0,0 +1,146 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <experimental/tuple>
+
+// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
+
+// Stress testing large arities with tuple and array.
+
+#include <experimental/tuple>
+#include <array>
+#include <utility>
+#include <cassert>
+
+////////////////////////////////////////////////////////////////////////////////
+template <class T, std::size_t Dummy = 0>
+struct always_imp
+{
+ typedef T type;
+};
+
+template <class T, std::size_t Dummy = 0>
+using always_t = typename always_imp<T, Dummy>::type;
+
+////////////////////////////////////////////////////////////////////////////////
+template <class Tuple, class Idx>
+struct make_function;
+
+template <class Tp, std::size_t ...Idx>
+struct make_function<Tp, std::integer_sequence<std::size_t, Idx...>>
+{
+ using type = bool (*)(always_t<Tp, Idx>...);
+};
+
+template <class Tp, std::size_t Size>
+using make_function_t = typename make_function<Tp, std::make_index_sequence<Size>>::type;
+
+////////////////////////////////////////////////////////////////////////////////
+template <class Tp, class Idx>
+struct make_tuple_imp;
+
+////////////////////////////////////////////////////////////////////////////////
+template <class Tp, std::size_t ...Idx>
+struct make_tuple_imp<Tp, std::integer_sequence<std::size_t, Idx...>>
+{
+ using type = std::tuple<always_t<Tp, Idx>...>;
+};
+
+template <class Tp, std::size_t Size>
+using make_tuple_t = typename make_tuple_imp<Tp, std::make_index_sequence<Size>>::type;
+
+template <class ...Types>
+bool test_apply_fn(Types...) { return true; }
+
+namespace ex = std::experimental;
+
+template <std::size_t Size>
+void test_all()
+{
+
+ using A = std::array<int, Size>;
+ using ConstA = std::array<int const, Size>;
+
+ using Tuple = make_tuple_t<int, Size>;
+ using CTuple = make_tuple_t<const int, Size>;
+
+ using ValFn = make_function_t<int, Size>;
+ ValFn val_fn = &test_apply_fn;
+
+ using RefFn = make_function_t<int &, Size>;
+ RefFn ref_fn = &test_apply_fn;
+
+ using CRefFn = make_function_t<int const &, Size>;
+ CRefFn cref_fn = &test_apply_fn;
+
+ using RRefFn = make_function_t<int &&, Size>;
+ RRefFn rref_fn = &test_apply_fn;
+
+ {
+ A a{};
+ assert(ex::apply(val_fn, a));
+ assert(ex::apply(ref_fn, a));
+ assert(ex::apply(cref_fn, a));
+ assert(ex::apply(rref_fn, std::move(a)));
+ }
+ {
+ ConstA a{};
+ assert(ex::apply(val_fn, a));
+ assert(ex::apply(cref_fn, a));
+ }
+ {
+ Tuple a{};
+ assert(ex::apply(val_fn, a));
+ assert(ex::apply(ref_fn, a));
+ assert(ex::apply(cref_fn, a));
+ assert(ex::apply(rref_fn, std::move(a)));
+ }
+ {
+ CTuple a{};
+ assert(ex::apply(val_fn, a));
+ assert(ex::apply(cref_fn, a));
+ }
+
+}
+
+
+template <std::size_t Size>
+void test_one()
+{
+ using A = std::array<int, Size>;
+ using Tuple = make_tuple_t<int, Size>;
+
+ using ValFn = make_function_t<int, Size>;
+ ValFn val_fn = &test_apply_fn;
+
+ {
+ A a{};
+ assert(ex::apply(val_fn, a));
+ }
+ {
+ Tuple a{};
+ assert(ex::apply(val_fn, a));
+ }
+}
+
+int main()
+{
+ // Instantiate with 1-5 arguments.
+ test_all<1>();
+ test_all<2>();
+ test_all<3>();
+ test_all<4>();
+ test_all<5>();
+
+ // Stress test with 128.
+ test_one<128>();
+ //test_one<256>();
+}
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp
new file mode 100644
index 00000000000..64ee66e6dec
--- /dev/null
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/ref_qualifiers.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <experimental/tuple>
+
+// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
+
+// Testing ref qualified functions
+
+#include <experimental/tuple>
+#include <cassert>
+
+struct func_obj
+{
+ constexpr func_obj() {}
+
+ constexpr int operator()() const & { return 1; }
+ constexpr int operator()() const && { return 2; }
+ constexpr int operator()() & { return 3; }
+ constexpr int operator()() && { return 4; }
+};
+
+namespace ex = std::experimental;
+
+int main()
+{
+ {
+ constexpr func_obj f;
+ constexpr std::tuple<> tp;
+
+ static_assert(1 == ex::apply(static_cast<func_obj const &>(f), tp), "");
+ static_assert(2 == ex::apply(static_cast<func_obj const &&>(f), tp), "");
+ }
+ {
+ func_obj f;
+ std::tuple<> tp;
+ assert(1 == ex::apply(static_cast<func_obj const &>(f), tp));
+ assert(2 == ex::apply(static_cast<func_obj const &&>(f), tp));
+ assert(3 == ex::apply(static_cast<func_obj &>(f), tp));
+ assert(4 == ex::apply(static_cast<func_obj &&>(f), tp));
+ }
+}
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/return_type.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/return_type.pass.cpp
new file mode 100644
index 00000000000..1ec38da5c04
--- /dev/null
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/return_type.pass.cpp
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <experimental/tuple>
+
+// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
+
+// Test the return type deduction.
+
+#include <experimental/tuple>
+#include <cassert>
+
+static int my_int = 42;
+
+template <int N> struct index {};
+
+void f(index<0>) {}
+
+int f(index<1>) { return 0; }
+int const f(index<2>) { return 0; }
+int volatile f(index<3>) { return 0; }
+int const volatile f(index<4>) { return 0; }
+
+int & f(index<5>) { return static_cast<int &>(my_int); }
+int const & f(index<6>) { return static_cast<int const &>(my_int); }
+int volatile & f(index<7>) { return static_cast<int volatile &>(my_int); }
+int const volatile & f(index<8>) { return static_cast<int const volatile &>(my_int); }
+
+int && f(index<9>) { return static_cast<int &&>(my_int); }
+int const && f(index<10>) { return static_cast<int const &&>(my_int); }
+int volatile && f(index<11>) { return static_cast<int volatile &&>(my_int); }
+int const volatile && f(index<12>) { return static_cast<int const volatile &&>(my_int); }
+
+int * f(index<13>) { return static_cast<int *>(&my_int); }
+int const * f(index<14>) { return static_cast<int const *>(&my_int); }
+int volatile * f(index<15>) { return static_cast<int volatile *>(&my_int); }
+int const volatile * f(index<16>) { return static_cast<int const volatile *>(&my_int); }
+
+
+template <int Func, class Expect>
+void test()
+{
+ using F = decltype((f(index<Func>{})));
+ static_assert(std::is_same<F, Expect>::value, "");
+}
+
+namespace ex = std::experimental;
+
+int main()
+{
+ test<0, void>();
+ test<1, int>();
+ //test<2, int const>();
+ //test<3, int volatile>();
+ //test<4, int const volatile>();
+ test<5, int &>();
+ test<6, int const &>();
+ test<7, int volatile &>();
+ test<8, int const volatile &>();
+ test<9, int &&>();
+ test<10, int const &&>();
+ test<11, int volatile &&>();
+ test<12, int const volatile &&>();
+ test<13, int *>();
+ test<14, int const *>();
+ test<15, int volatile *>();
+ test<16, int const volatile *>();
+}
diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple.apply/types.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/types.pass.cpp
new file mode 100644
index 00000000000..5d3d564c26f
--- /dev/null
+++ b/libcxx/test/std/experimental/utilities/tuple/tuple.apply/types.pass.cpp
@@ -0,0 +1,427 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <experimental/tuple>
+
+// template <class F, class T> constexpr decltype(auto) apply(F &&, T &&)
+
+// Test function types.
+
+#include <experimental/tuple>
+#include <array>
+#include <utility>
+#include <cassert>
+
+namespace ex = std::experimental;
+
+int count = 0;
+
+void f_void_0() { ++count; }
+void f_void_1(int i) { count += i; }
+void f_void_2(int x, int y) { count += (x + y); }
+void f_void_3(int x, int y, int z) { count += (x + y + z); }
+
+int f_int_0() { return ++count; }
+int f_int_1(int x) { return count += x; }
+int f_int_2(int x, int y) { return count += (x + y); }
+int f_int_3(int x, int y, int z) { return count += (x + y + z); }
+
+struct A_void_0
+{
+ A_void_0() {}
+ void operator()() { ++count; }
+ void operator()() const { ++count; ++count; }
+};
+
+struct A_void_1
+{
+ A_void_1() {}
+ void operator()(int x) { count += x; }
+ void operator()(int x) const { count += x + 1; }
+};
+
+struct A_void_2
+{
+ A_void_2() {}
+ void operator()(int x, int y) { count += (x + y); }
+ void operator()(int x, int y) const { count += (x + y) + 1; }
+};
+
+struct A_void_3
+{
+ A_void_3() {}
+ void operator()(int x, int y, int z) { count += (x + y + z); }
+ void operator()(int x, int y, int z) const { count += (x + y + z) + 1; }
+};
+
+
+struct A_int_0
+{
+ A_int_0() {}
+ int operator()() { return ++count; }
+ int operator()() const { ++count; return ++count; }
+};
+
+struct A_int_1
+{
+ A_int_1() {}
+ int operator()(int x) { return count += x; }
+ int operator()(int x) const { return count += (x + 1); }
+
+};
+
+struct A_int_2
+{
+ A_int_2() {}
+ int operator()(int x, int y) { return count += (x + y); }
+ int operator()(int x, int y) const { return count += (x + y + 1); }
+};
+
+struct A_int_3
+{
+ A_int_3() {}
+ int operator()(int x, int y, int z) { return count += (x + y + z); }
+ int operator()(int x, int y, int z) const { return count += (x + y + z + 1); }
+};
+
+
+template <class Tuple>
+void test_void_0()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{};
+ ex::apply(f_void_0, t);
+ assert(count == 1);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{};
+ auto fp = &f_void_0;
+ ex::apply(fp, t);
+ assert(count == 1);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{};
+ A_void_0 a;
+ ex::apply(a, t);
+ assert(count == 1);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{};
+ A_void_0 const a;
+ ex::apply(a, t);
+ assert(count == 2);
+ }
+}
+
+template <class Tuple>
+void test_void_1()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{1};
+ ex::apply(f_void_1, t);
+ assert(count == 1);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{2};
+ void (*fp)(int) = f_void_1;
+ ex::apply(fp, t);
+ assert(count == 2);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{3};
+ A_void_1 fn;
+ ex::apply(fn, t);
+ assert(count == 3);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{4};
+ A_void_1 const a;
+ ex::apply(a, t);
+ assert(count == 5);
+ }
+}
+
+template <class Tuple>
+void test_void_2()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{1, 2};
+ ex::apply(f_void_2, t);
+ assert(count == 3);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{2, 3};
+ auto fp = &f_void_2;
+ ex::apply(fp, t);
+ assert(count == 5);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{3, 4};
+ A_void_2 a;
+ ex::apply(a, t);
+ assert(count == 7);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{4, 5};
+ A_void_2 const a;
+ ex::apply(a, t);
+ assert(count == 10);
+ }
+}
+
+template <class Tuple>
+void test_void_3()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{1, 2, 3};
+ ex::apply(f_void_3, t);
+ assert(count == 6);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{2, 3, 4};
+ auto fp = &f_void_3;
+ ex::apply(fp, t);
+ assert(count == 9);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{3, 4, 5};
+ A_void_3 a;
+ ex::apply(a, t);
+ assert(count == 12);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{4, 5, 6};
+ A_void_3 const a;
+ ex::apply(a, t);
+ assert(count == 16);
+ }
+}
+
+
+
+template <class Tuple>
+void test_int_0()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{};
+ assert(1 == ex::apply(f_int_0, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{};
+ auto fp = &f_int_0;
+ assert(1 == ex::apply(fp, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{};
+ A_int_0 a;
+ assert(1 == ex::apply(a, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{};
+ A_int_0 const a;
+ assert(2 == ex::apply(a, t));
+ assert(count == 2);
+ }
+}
+
+template <class Tuple>
+void test_int_1()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{1};
+ assert(1 == ex::apply(f_int_1, t));
+ assert(count == 1);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{2};
+ int (*fp)(int) = f_int_1;
+ assert(2 == ex::apply(fp, t));
+ assert(count == 2);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{3};
+ A_int_1 fn;
+ assert(3 == ex::apply(fn, t));
+ assert(count == 3);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{4};
+ A_int_1 const a;
+ assert(5 == ex::apply(a, t));
+ assert(count == 5);
+ }
+}
+
+template <class Tuple>
+void test_int_2()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{1, 2};
+ assert(3 == ex::apply(f_int_2, t));
+ assert(count == 3);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{2, 3};
+ auto fp = &f_int_2;
+ assert(5 == ex::apply(fp, t));
+ assert(count == 5);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{3, 4};
+ A_int_2 a;
+ assert(7 == ex::apply(a, t));
+ assert(count == 7);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{4, 5};
+ A_int_2 const a;
+ assert(10 == ex::apply(a, t));
+ assert(count == 10);
+ }
+}
+
+template <class Tuple>
+void test_int_3()
+{
+ count = 0;
+ // function
+ {
+ Tuple t{1, 2, 3};
+ assert(6 == ex::apply(f_int_3, t));
+ assert(count == 6);
+ }
+ count = 0;
+ // function pointer
+ {
+ Tuple t{2, 3, 4};
+ auto fp = &f_int_3;
+ assert(9 == ex::apply(fp, t));
+ assert(count == 9);
+ }
+ count = 0;
+ // functor
+ {
+ Tuple t{3, 4, 5};
+ A_int_3 a;
+ assert(12 == ex::apply(a, t));
+ assert(count == 12);
+ }
+ count = 0;
+ // const functor
+ {
+ Tuple t{4, 5, 6};
+ A_int_3 const a;
+ assert(16 == ex::apply(a, t));
+ assert(count == 16);
+ }
+}
+
+template <class Tuple>
+void test_0()
+{
+ test_void_0<Tuple>();
+ test_int_0<Tuple>();
+}
+
+template <class Tuple>
+void test_1()
+{
+ test_void_1<Tuple>();
+ test_int_1<Tuple>();
+}
+
+template <class Tuple>
+void test_2()
+{
+ test_void_2<Tuple>();
+ test_int_2<Tuple>();
+}
+
+template <class Tuple>
+void test_3()
+{
+ test_void_3<Tuple>();
+ test_int_3<Tuple>();
+}
+
+int main()
+{
+ test_0<std::tuple<>>();
+
+ test_1<std::tuple<int>>();
+ test_1<std::array<int, 1>>();
+
+ test_2<std::tuple<int, int>>();
+ test_2<std::pair<int, int>>();
+ test_2<std::array<int, 2>>();
+
+ test_3<std::tuple<int, int, int>>();
+ test_3<std::array<int, 3>>();
+}
OpenPOWER on IntegriCloud