Commit 93e95400 by Jonathan Wakely Committed by Jonathan Wakely

Implement C++17 std::invoke and LWG DR 2219

	* include/std/functional (__invoke_impl): New overloads.
	(__invoke): Replace with a single function calling __invoke_impl.
	(invoke): Add C++17 std::invoke.
	(reference_wrapper::operator()): Qualify call to __invoke.
	(_Mem_fn_traits_base, _Mem_fn_traits): Remove unused typedefs.
	(_Mem_fn_base): Remove unused typedefs and implement call operator in
	terms of __invoke.
	* include/std/future (__future_base::_Async_state_commonV2): Do not
	pass reference_wrapper as object argument to call_once.
	* include/std/type_traits (result_of): Define nested __invoke_type.
	Handle reference_wrapper as per LWG 2219.
	* testsuite/20_util/bind/ref_neg.cc: Adjust dg-error directives.
	* testsuite/20_util/function_objects/mem_fn/55463.cc: Remove tests
	using member functions of reference_wrapper.

From-SVN: r229290
parent 6fbd5984
2015-10-24 Jonathan Wakely <jwakely@redhat.com>
* include/std/functional (__invoke_impl): New overloads.
(__invoke): Replace with a single function calling __invoke_impl.
(invoke): Add C++17 std::invoke.
(reference_wrapper::operator()): Qualify call to __invoke.
(_Mem_fn_traits_base, _Mem_fn_traits): Remove unused typedefs.
(_Mem_fn_base): Remove unused typedefs and implement call operator in
terms of __invoke.
* include/std/future (__future_base::_Async_state_commonV2): Do not
pass reference_wrapper as object argument to call_once.
* include/std/type_traits (result_of): Define nested __invoke_type.
Handle reference_wrapper as per LWG 2219.
* testsuite/20_util/bind/ref_neg.cc: Adjust dg-error directives.
* testsuite/20_util/function_objects/mem_fn/55463.cc: Remove tests
using member functions of reference_wrapper.
2015-10-24 Jonathan Wakely <jwakely@redhat.com>
* include/std/future (async): Use deferred function on exception.
* testsuite/30_threads/async/except.cc: New.
......
......@@ -1641,7 +1641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// the shared state, whichever happens first.
virtual void _M_complete_async() { _M_join(); }
void _M_join() { std::call_once(_M_once, &thread::join, ref(_M_thread)); }
void _M_join() { std::call_once(_M_once, &thread::join, &_M_thread); }
thread _M_thread;
once_flag _M_once;
......
......@@ -2219,13 +2219,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define __cpp_lib_result_of_sfinae 201210
struct __invoke_memfun_ref { };
struct __invoke_memfun_deref { };
struct __invoke_memobj_ref { };
struct __invoke_memobj_deref { };
struct __invoke_other { };
// Associate a tag type with a specialization of __success_type.
template<typename _Tp, typename _Tag>
struct __result_of_success : __success_type<_Tp>
{ using __invoke_type = _Tag; };
// [func.require] paragraph 1 bullet 1:
struct __result_of_memfun_ref_impl
{
template<typename _Fp, typename _Tp1, typename... _Args>
static __success_type<decltype(
static __result_of_success<decltype(
(std::declval<_Tp1>().*std::declval<_Fp>())(std::declval<_Args>()...)
)> _S_test(int);
), __invoke_memfun_ref> _S_test(int);
template<typename...>
static __failure_type _S_test(...);
......@@ -2242,9 +2253,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __result_of_memfun_deref_impl
{
template<typename _Fp, typename _Tp1, typename... _Args>
static __success_type<decltype(
static __result_of_success<decltype(
((*std::declval<_Tp1>()).*std::declval<_Fp>())(std::declval<_Args>()...)
)> _S_test(int);
), __invoke_memfun_deref> _S_test(int);
template<typename...>
static __failure_type _S_test(...);
......@@ -2261,9 +2272,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __result_of_memobj_ref_impl
{
template<typename _Fp, typename _Tp1>
static __success_type<decltype(
static __result_of_success<decltype(
std::declval<_Tp1>().*std::declval<_Fp>()
)> _S_test(int);
), __invoke_memobj_ref> _S_test(int);
template<typename, typename>
static __failure_type _S_test(...);
......@@ -2280,9 +2291,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __result_of_memobj_deref_impl
{
template<typename _Fp, typename _Tp1>
static __success_type<decltype(
static __result_of_success<decltype(
(*std::declval<_Tp1>()).*std::declval<_Fp>()
)> _S_test(int);
), __invoke_memobj_deref> _S_test(int);
template<typename, typename>
static __failure_type _S_test(...);
......@@ -2327,6 +2338,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>::type::type type;
};
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2219. INVOKE-ing a pointer to member with a reference_wrapper
// as the object expression
template<typename> struct reference_wrapper;
template<typename _Res, typename _Class, typename _Arg>
struct __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>>
: __result_of_memobj<_Res _Class::*, _Arg>
{
typedef typename
__result_of_memobj_ref<_Res _Class::*, _Arg&>::type type;
};
template<typename _Res, typename _Class, typename _Arg>
struct __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>&>
: __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>>
{ };
template<typename _Res, typename _Class, typename _Arg>
struct __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>&&>
: __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>>
{ };
template<typename _Res, typename _Class, typename _Arg, typename... _Args>
struct __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>, _Args...>
: __result_of_memfun<_Res _Class::*, _Arg&, _Args...>
{
typedef typename
__result_of_memfun_ref<_Res _Class::*, _Arg&, _Args...>::type type;
};
template<typename _Res, typename _Class, typename _Arg, typename... _Args>
struct __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>&,
_Args...>
: __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>, _Args...>
{ };
template<typename _Res, typename _Class, typename _Arg, typename... _Args>
struct __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>&&,
_Args...>
: __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>, _Args...>
{ };
template<bool, bool, typename _Functor, typename... _ArgTypes>
struct __result_of_impl
{
......@@ -2347,9 +2401,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __result_of_other_impl
{
template<typename _Fn, typename... _Args>
static __success_type<decltype(
static __result_of_success<decltype(
std::declval<_Fn>()(std::declval<_Args>()...)
)> _S_test(int);
), __invoke_other> _S_test(int);
template<typename...>
static __failure_type _S_test(...);
......
......@@ -30,10 +30,6 @@ void test01()
{
const int dummy = 0;
std::bind(&inc, _1)(0); // { dg-error "no match" }
// { dg-error "rvalue|const" "" { target *-*-* } 1125 }
// { dg-error "rvalue|const" "" { target *-*-* } 1139 }
// { dg-error "rvalue|const" "" { target *-*-* } 1153 }
// { dg-error "rvalue|const" "" { target *-*-* } 1167 }
std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" }
}
......@@ -50,8 +46,15 @@ void test02()
const int dummy = 0;
std::bind(Inc(), _1)(dummy); // { dg-error "no match" }
std::bind(&Inc::f, Inc(), std::ref(dummy))(); // { dg-error "no match" }
// { dg-error "no match" "" { target *-*-* } 594 }
// { dg-error "no type" "" { target *-*-* } 237 }
}
// { dg-error "rvalue|const" "" { target *-*-* } 1024 }
// { dg-error "rvalue|const" "" { target *-*-* } 1038 }
// { dg-error "rvalue|const" "" { target *-*-* } 1052 }
// { dg-error "rvalue|const" "" { target *-*-* } 1066 }
int main()
{
test01();
......
......@@ -98,15 +98,3 @@ void test01()
int& pval __attribute__((unused)) = std::mem_fn( &X::data )( X_ptr() );
int& sval __attribute__((unused)) = std::mem_fn( &X::data )( smart_ptr() );
}
void test02()
{
std::reference_wrapper<X> r = ref();
X& x1 __attribute__((unused))
= std::mem_fn( &std::reference_wrapper<X>::get )( r );
const std::reference_wrapper<X> cr = ref();
const X& x3 __attribute__((unused))
= std::mem_fn( &std::reference_wrapper<X>::get )( cr );
X& x2 __attribute__((unused))
= std::mem_fn( &std::reference_wrapper<X>::get )( ref() );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment