diff options
author | Eric Fiselier <eric@efcs.ca> | 2015-03-17 18:28:14 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2015-03-17 18:28:14 +0000 |
commit | ea10d2477ac14bbe31d18c6ce362525c33c06e38 (patch) | |
tree | c656cba8073cb8e23d704c719cb4430fc6fd43be /libcxx | |
parent | 0353f279f1b564ccc956273e11394830a56e8df9 (diff) | |
download | bcm5719-llvm-ea10d2477ac14bbe31d18c6ce362525c33c06e38.tar.gz bcm5719-llvm-ea10d2477ac14bbe31d18c6ce362525c33c06e38.zip |
[libcxx] Add <experimental/tuple> header for LFTS.
Summary:
This patch adds the `<experimental/tuple>` header (almost) as specified in the latest draft of the library fundamentals TS.
The main changes in this patch are:
1. Added variable template `tuple_size_v`
2. Added function `apply(Func &&, Tuple &&)`.
3. Changed `__invoke` to be `_LIBCPP_CONSTEXPR_AFTER_CXX11`.
The `apply(...)` implementation uses `__invoke` to invoke the given function. `__invoke` already provides the required functionality. Using `__invoke` also allows `apply` to be used on pointers to member function/objects as an extension. In order to facilitate this `__invoke` has to be marked `constexpr`.
Test Plan:
Each new feature was tested.
The test cases for `tuple_size_v` are as follows:
1. tuple_size_v.pass.cpp
- Check `tuple_size_v` on cv qualified tuples, pairs and arrays.
2. tuple_size_v.fail.cpp
- Test on reference type.
3. tuple_size_v_2.fail.cpp
- Test on non-tuple
4. tuple_size_v_3.fail.cpp
- Test on pointer type.
The test cases for tuple.apply are as follows:
1. arg_type.pass.cpp
- Ensure that ref/pointer/cv qualified types are properly passed.
2. constexpr_types.pass.cpp
- Ensure constexpr evaluation of apply is possible for `tuple` and `pair`.
3. extended_types.pass.cpp
- Test apply on function types permitted by extension.
4. large_arity.pass.cpp
- Test that apply can evaluated on tuples and arrays with large sizes.
5. ref_qualifiers.pass.cpp
- Test that apply respects ref qualified functions.
6. return_type.pass.cpp
- Test that apply returns the proper type.
7. types.pass.cpp
- Test apply on function types as required by LFTS.
Reviewers: mclow.lists
Reviewed By: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D4512
llvm-svn: 232515
Diffstat (limited to 'libcxx')
18 files changed, 1694 insertions, 11 deletions
diff --git a/libcxx/include/__functional_base b/libcxx/include/__functional_base index 09424bc025a..64bc93116f0 100644 --- a/libcxx/include/__functional_base +++ b/libcxx/include/__functional_base @@ -364,7 +364,7 @@ struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> template <class _Fp, class _A0, class ..._Args, class> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)) @@ -374,7 +374,7 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) template <class _Fp, class _A0, class ..._Args, class> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)) @@ -386,7 +386,7 @@ __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) template <class _Fp, class _A0, class> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype(_VSTD::forward<_A0>(__a0).*__f) @@ -396,7 +396,7 @@ __invoke(_Fp&& __f, _A0&& __a0) template <class _Fp, class _A0, class> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype((*_VSTD::forward<_A0>(__a0)).*__f) @@ -407,7 +407,7 @@ __invoke(_Fp&& __f, _A0&& __a0) // bullet 5 template <class _Fp, class ..._Args> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _Args&& ...__args) -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)) diff --git a/libcxx/include/experimental/tuple b/libcxx/include/experimental/tuple new file mode 100644 index 00000000000..34133b2d150 --- /dev/null +++ b/libcxx/include/experimental/tuple @@ -0,0 +1,81 @@ +// -*- C++ -*- +//===----------------------------- tuple ----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXPERIMENTAL_TUPLE +#define _LIBCPP_EXPERIMENTAL_TUPLE + +/* + experimental/tuple synopsis + +// C++1y + +#include <tuple> + +namespace std { +namespace experimental { +inline namespace fundamentals_v1 { + + // See C++14 20.4.2.5, tuple helper classes + template <class T> constexpr size_t tuple_size_v + = tuple_size<T>::value; + + // 3.2.2, Calling a function with a tuple of arguments + template <class F, class Tuple> + constexpr decltype(auto) apply(F&& f, Tuple&& t); + +} // namespace fundamentals_v1 +} // namespace experimental +} // namespace std + + */ + +# include <experimental/__config> + +#if _LIBCPP_STD_VER > 11 + +# include <tuple> +# include <utility> +# include <__functional_base> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_LFTS + +#ifndef _LIBCPP_HAS_NO_VARIABLE_TEMPLATES +template <class _Tp> +_LIBCPP_CONSTEXPR size_t tuple_size_v = tuple_size<_Tp>::value; +#endif + +template <class _Fn, class _Tuple, size_t ..._Id> +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +decltype(auto) __apply_tuple_impl(_Fn && __f, _Tuple && __t, + integer_sequence<size_t, _Id...>) { + return _VSTD::__invoke( + _VSTD::forward<_Fn>(__f), + _VSTD::get<_Id>(_VSTD::forward<_Tuple>(__t))... + ); +} + +template <class _Fn, class _Tuple> +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 +decltype(auto) apply(_Fn && __f, _Tuple && __t) { + return _VSTD_LFTS::__apply_tuple_impl( + _VSTD::forward<_Fn>(__f), _VSTD::forward<_Tuple>(__t), + make_index_sequence<tuple_size<typename decay<_Tuple>::type>::value>() + ); +} + +_LIBCPP_END_NAMESPACE_LFTS + +#endif /* _LIBCPP_STD_VER > 11 */ + +#endif /* _LIBCPP_EXPERIMENTAL_TUPLE */ diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 1820bb2e4bc..0655a685a2e 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -3440,7 +3440,7 @@ template <class _Fp, class _A0, class ..._Args, typename remove_reference<_A0>::type>::value >::type > -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype((_VSTD::forward<_A0>(__a0).*__f)(_VSTD::forward<_Args>(__args)...)); @@ -3453,7 +3453,7 @@ template <class _Fp, class _A0, class ..._Args, typename remove_reference<_A0>::type>::value >::type > -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) -> decltype(((*_VSTD::forward<_A0>(__a0)).*__f)(_VSTD::forward<_Args>(__args)...)); @@ -3468,7 +3468,7 @@ template <class _Fp, class _A0, typename remove_reference<_A0>::type>::value >::type > -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype(_VSTD::forward<_A0>(__a0).*__f); @@ -3481,7 +3481,7 @@ template <class _Fp, class _A0, typename remove_reference<_A0>::type>::value >::type > -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _A0&& __a0) -> decltype((*_VSTD::forward<_A0>(__a0)).*__f); @@ -3489,7 +3489,7 @@ __invoke(_Fp&& __f, _A0&& __a0) // bullet 5 template <class _Fp, class ..._Args> -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 auto __invoke(_Fp&& __f, _Args&& ...__args) -> decltype(_VSTD::forward<_Fp>(__f)(_VSTD::forward<_Args>(__args)...)); diff --git a/libcxx/test/libcxx/experimental/utilities/tuple/header.tuple.synop/includes.pass.cpp b/libcxx/test/libcxx/experimental/utilities/tuple/header.tuple.synop/includes.pass.cpp new file mode 100644 index 00000000000..544ddfb269f --- /dev/null +++ b/libcxx/test/libcxx/experimental/utilities/tuple/header.tuple.synop/includes.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <experimental/tuple> + +#include <experimental/tuple> + +int main() +{ +#if _LIBCPP_STD_VER > 11 +# ifndef _LIBCPP_TUPLE +# error "<experimental/tuple> must include <tuple>" +# endif +#endif /* _LIBCPP_STD_VER > 11 */ +} diff --git a/libcxx/test/libcxx/experimental/utilities/tuple/version.pass.cpp b/libcxx/test/libcxx/experimental/utilities/tuple/version.pass.cpp new file mode 100644 index 00000000000..5a3fd2e3964 --- /dev/null +++ b/libcxx/test/libcxx/experimental/utilities/tuple/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <experimental/tuple> + +#include <experimental/tuple> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/libcxx/test/std/experimental/utilities/tuple/header.tuple.synop/includes.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/header.tuple.synop/includes.pass.cpp new file mode 100644 index 00000000000..d37557a7b17 --- /dev/null +++ b/libcxx/test/std/experimental/utilities/tuple/header.tuple.synop/includes.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +#include <experimental/tuple> + +int main() +{ + std::tuple<int> x(1); +} 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>>(); +} diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple_size_v.fail.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v.fail.cpp new file mode 100644 index 00000000000..a25b18cf538 --- /dev/null +++ b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 T> constexpr size_t tuple_size_v = tuple_size<T>::value; + +// Test with reference + +#include <experimental/tuple> + +namespace ex = std::experimental; + +int main() +{ + auto x = ex::tuple_size_v<std::tuple<> &>; +} diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple_size_v.pass.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v.pass.cpp new file mode 100644 index 00000000000..d7a5aa679fc --- /dev/null +++ b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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 T> constexpr size_t tuple_size_v = tuple_size<T>::value; + +#include <experimental/tuple> +#include <utility> +#include <array> + +namespace ex = std::experimental; + +template <class Tuple, int Expect> +void test() +{ + static_assert(ex::tuple_size_v<Tuple> == Expect, ""); + static_assert(ex::tuple_size_v<Tuple> == std::tuple_size<Tuple>::value, ""); + static_assert(ex::tuple_size_v<Tuple const> == std::tuple_size<Tuple>::value, ""); + static_assert(ex::tuple_size_v<Tuple volatile> == std::tuple_size<Tuple>::value, ""); + static_assert(ex::tuple_size_v<Tuple const volatile> == std::tuple_size<Tuple>::value, ""); +} + +int main() +{ + test<std::tuple<>, 0>(); + + test<std::tuple<int>, 1>(); + test<std::array<int, 1>, 1>(); + + test<std::tuple<int, int>, 2>(); + test<std::pair<int, int>, 2>(); + test<std::array<int, 2>, 2>(); + + test<std::tuple<int, int, int>, 3>(); + test<std::array<int, 3>, 3>(); +} diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple_size_v_2.fail.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v_2.fail.cpp new file mode 100644 index 00000000000..a95ac49ff45 --- /dev/null +++ b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v_2.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 T> constexpr size_t tuple_size_v = tuple_size<T>::value; + +// Test with non tuple type + +#include <experimental/tuple> + +namespace ex = std::experimental; + +int main() +{ + auto x = ex::tuple_size_v<int>; +} diff --git a/libcxx/test/std/experimental/utilities/tuple/tuple_size_v_3.fail.cpp b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v_3.fail.cpp new file mode 100644 index 00000000000..7c2f0cc236f --- /dev/null +++ b/libcxx/test/std/experimental/utilities/tuple/tuple_size_v_3.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 T> constexpr size_t tuple_size_v = tuple_size<T>::value; + +// Test with pointer + +#include <experimental/tuple> + +namespace ex = std::experimental; + +int main() +{ + auto x = ex::tuple_size_v<std::tuple<>*>; +} diff --git a/libcxx/www/ts1z_status.html b/libcxx/www/ts1z_status.html index d3d29c20f3b..59cfe5e3369 100644 --- a/libcxx/www/ts1z_status.html +++ b/libcxx/www/ts1z_status.html @@ -67,7 +67,7 @@ <tr><td>Additions to std::packaged_task</td><td>Not started</td></tr> <tr><td></td><td></td></tr> <tr><td>Class erased_type</td><td>Complete</td></tr> - <tr><td>Calling a function with a tuple of arguments</td><td>Implementation in progress</td></tr> + <tr><td>Calling a function with a tuple of arguments</td><td>Complete</td></tr> <tr><td>Other type transformations</td><td>Not started</td></tr> <tr><td>Compile-time Rational Arithmetic</td><td>Implementation in progress</td></tr> <tr><td>Time Utilities</td><td>Complete</td></tr> |