[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 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@232515 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4d23cc6f55
commit
13858ee056
@ -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)...))
|
||||
|
81
include/experimental/tuple
Normal file
81
include/experimental/tuple
Normal file
@ -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 */
|
@ -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)...));
|
||||
|
@ -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 */
|
||||
}
|
20
test/libcxx/experimental/utilities/tuple/version.pass.cpp
Normal file
20
test/libcxx/experimental/utilities/tuple/version.pass.cpp
Normal file
@ -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()
|
||||
{
|
||||
}
|
@ -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);
|
||||
}
|
@ -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>>();
|
||||
}
|
@ -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>>();
|
||||
}
|
@ -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>
|
||||
>();
|
||||
}
|
||||
}
|
@ -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>();
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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 *>();
|
||||
}
|
427
test/std/experimental/utilities/tuple/tuple.apply/types.pass.cpp
Normal file
427
test/std/experimental/utilities/tuple/tuple.apply/types.pass.cpp
Normal file
@ -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>>();
|
||||
}
|
25
test/std/experimental/utilities/tuple/tuple_size_v.fail.cpp
Normal file
25
test/std/experimental/utilities/tuple/tuple_size_v.fail.cpp
Normal file
@ -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<> &>;
|
||||
}
|
45
test/std/experimental/utilities/tuple/tuple_size_v.pass.cpp
Normal file
45
test/std/experimental/utilities/tuple/tuple_size_v.pass.cpp
Normal file
@ -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>();
|
||||
}
|
@ -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>;
|
||||
}
|
@ -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<>*>;
|
||||
}
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user