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
This commit is contained in:
parent
6fbd598400
commit
93e954005f
6 changed files with 175 additions and 214 deletions
|
@ -1,3 +1,20 @@
|
|||
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.
|
||||
|
|
|
@ -184,48 +184,77 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
: _Weak_result_type_impl<typename remove_cv<_Functor>::type>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* Invoke a function object, which may be either a member pointer or a
|
||||
* function object. The first parameter will tell which.
|
||||
*/
|
||||
template<typename _Functor, typename... _Args>
|
||||
inline
|
||||
typename enable_if<
|
||||
(!is_member_pointer<_Functor>::value
|
||||
&& !is_function<_Functor>::value
|
||||
&& !is_function<typename remove_pointer<_Functor>::type>::value),
|
||||
typename result_of<_Functor&(_Args&&...)>::type
|
||||
>::type
|
||||
__invoke(_Functor& __f, _Args&&... __args)
|
||||
template<typename _Res, typename _Fn, typename... _Args>
|
||||
inline _Res
|
||||
__invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
|
||||
noexcept(noexcept(std::forward<_Fn>(__f)(std::forward<_Args>(__args)...)))
|
||||
{ return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
inline _Res
|
||||
__invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t,
|
||||
_Args&&... __args)
|
||||
noexcept(noexcept((forward<_Tp>(__t).*__f)(forward<_Args>(__args)...)))
|
||||
{ return (forward<_Tp>(__t).*__f)(forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
inline _Res
|
||||
__invoke_impl(__invoke_memfun_ref, _MemFun&& __f,
|
||||
reference_wrapper<_Tp> __t, _Args&&... __args)
|
||||
noexcept(noexcept((__t.get().*__f)(forward<_Args>(__args)...)))
|
||||
{ return (__t.get().*__f)(forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
inline _Res
|
||||
__invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t,
|
||||
_Args&&... __args)
|
||||
noexcept(noexcept(((*forward<_Tp>(__t)).*__f)(forward<_Args>(__args)...)))
|
||||
{ return ((*forward<_Tp>(__t)).*__f)(forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
inline _Res
|
||||
__invoke_impl(__invoke_memobj_ref, _MemFun&& __f, _Tp&& __t)
|
||||
noexcept(noexcept(forward<_Tp>(__t).*__f))
|
||||
{ return forward<_Tp>(__t).*__f; }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
inline _Res
|
||||
__invoke_impl(__invoke_memobj_ref, _MemFun&& __f,
|
||||
reference_wrapper<_Tp> __t)
|
||||
noexcept(noexcept(__t.get().*__f))
|
||||
{ return __t.get().*__f; }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
inline _Res
|
||||
__invoke_impl(__invoke_memobj_deref, _MemFun&& __f, _Tp&& __t,
|
||||
_Args&&... __args)
|
||||
noexcept(noexcept((*forward<_Tp>(__t)).*__f))
|
||||
{ return (*forward<_Tp>(__t)).*__f; }
|
||||
|
||||
/// Invoke a callable object.
|
||||
template<typename _Callable, typename... _Args>
|
||||
inline typename result_of<_Callable&&(_Args&&...)>::type
|
||||
__invoke(_Callable&& __fn, _Args&&... __args)
|
||||
{
|
||||
return __f(std::forward<_Args>(__args)...);
|
||||
using __result_of = result_of<_Callable&&(_Args&&...)>;
|
||||
using __type = typename __result_of::type;
|
||||
using __tag = typename __result_of::__invoke_type;
|
||||
return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template<typename _Functor, typename... _Args>
|
||||
inline
|
||||
typename enable_if<
|
||||
(is_member_pointer<_Functor>::value
|
||||
&& !is_function<_Functor>::value
|
||||
&& !is_function<typename remove_pointer<_Functor>::type>::value),
|
||||
typename result_of<_Functor(_Args&&...)>::type
|
||||
>::type
|
||||
__invoke(_Functor& __f, _Args&&... __args)
|
||||
{
|
||||
return std::mem_fn(__f)(std::forward<_Args>(__args)...);
|
||||
}
|
||||
#if __cplusplus > 201402L
|
||||
# define __cpp_lib_invoke 201411
|
||||
|
||||
// To pick up function references (that will become function pointers)
|
||||
template<typename _Functor, typename... _Args>
|
||||
inline
|
||||
typename enable_if<
|
||||
(is_pointer<_Functor>::value
|
||||
&& is_function<typename remove_pointer<_Functor>::type>::value),
|
||||
typename result_of<_Functor(_Args&&...)>::type
|
||||
>::type
|
||||
__invoke(_Functor __f, _Args&&... __args)
|
||||
/// Invoke a callable object.
|
||||
template<typename _Callable, typename... _Args>
|
||||
inline result_of_t<_Callable&&(_Args&&...)>
|
||||
invoke(_Callable&& __fn, _Args&&... __args)
|
||||
{
|
||||
return __f(std::forward<_Args>(__args)...);
|
||||
return std::__invoke(std::forward<_Callable>(__fn),
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Knowing which of unary_function and binary_function _Tp derives
|
||||
|
@ -425,7 +454,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
typename result_of<_Tp&(_Args&&...)>::type
|
||||
operator()(_Args&&... __args) const
|
||||
{
|
||||
return __invoke(get(), std::forward<_Args>(__args)...);
|
||||
return std::__invoke(get(), std::forward<_Args>(__args)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -504,8 +533,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
struct _Mem_fn_traits_base
|
||||
{
|
||||
using __result_type = _Res;
|
||||
using __class_type = _Class;
|
||||
using __arg_types = _Pack<_ArgTypes...>;
|
||||
using __maybe_type
|
||||
= _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>;
|
||||
using __arity = integral_constant<size_t, sizeof...(_ArgTypes)>;
|
||||
|
@ -516,18 +543,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \
|
||||
: _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \
|
||||
{ \
|
||||
using __pmf_type = _Res (_Class::*)(_ArgTypes...) _CV _REF; \
|
||||
using __lvalue = _LVAL; \
|
||||
using __rvalue = _RVAL; \
|
||||
using __vararg = false_type; \
|
||||
}; \
|
||||
template<typename _Res, typename _Class, typename... _ArgTypes> \
|
||||
struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \
|
||||
: _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \
|
||||
{ \
|
||||
using __pmf_type = _Res (_Class::*)(_ArgTypes... ...) _CV _REF; \
|
||||
using __lvalue = _LVAL; \
|
||||
using __rvalue = _RVAL; \
|
||||
using __vararg = true_type; \
|
||||
};
|
||||
|
||||
|
@ -551,173 +572,51 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
|
|||
{
|
||||
using _Traits = _Mem_fn_traits<_MemFunPtr>;
|
||||
|
||||
using _Class = typename _Traits::__class_type;
|
||||
using _ArgTypes = typename _Traits::__arg_types;
|
||||
using _Pmf = typename _Traits::__pmf_type;
|
||||
|
||||
using _Arity = typename _Traits::__arity;
|
||||
using _Varargs = typename _Traits::__vararg;
|
||||
|
||||
template<typename _Func, typename... _BoundArgs>
|
||||
friend struct _Bind_check_arity;
|
||||
|
||||
// for varargs functions we just check the number of arguments,
|
||||
// otherwise we also check they are convertible.
|
||||
template<typename _Args>
|
||||
using _CheckArgs = typename conditional<_Varargs::value,
|
||||
__bool_constant<(_Args::value >= _ArgTypes::value)>,
|
||||
_AllConvertible<_Args, _ArgTypes>
|
||||
>::type;
|
||||
_MemFunPtr _M_pmf;
|
||||
|
||||
public:
|
||||
|
||||
using result_type = typename _Traits::__result_type;
|
||||
|
||||
explicit constexpr _Mem_fn_base(_Pmf __pmf) : _M_pmf(__pmf) { }
|
||||
explicit constexpr
|
||||
_Mem_fn_base(_MemFunPtr __pmf) noexcept : _M_pmf(__pmf) { }
|
||||
|
||||
// Handle objects
|
||||
template<typename... _Args, typename _Req
|
||||
= _Require<typename _Traits::__lvalue,
|
||||
_CheckArgs<_Pack<_Args...>>>>
|
||||
result_type
|
||||
operator()(_Class& __object, _Args&&... __args) const
|
||||
{ return (__object.*_M_pmf)(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename... _Args, typename _Req
|
||||
= _Require<typename _Traits::__rvalue,
|
||||
_CheckArgs<_Pack<_Args...>>>>
|
||||
result_type
|
||||
operator()(_Class&& __object, _Args&&... __args) const
|
||||
{
|
||||
return (std::move(__object).*_M_pmf)(std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
// Handle pointers
|
||||
template<typename... _Args, typename _Req
|
||||
= _Require<typename _Traits::__lvalue,
|
||||
_CheckArgs<_Pack<_Args...>>>>
|
||||
result_type
|
||||
operator()(_Class* __object, _Args&&... __args) const
|
||||
{ return (__object->*_M_pmf)(std::forward<_Args>(__args)...); }
|
||||
|
||||
// Handle smart pointers, references and pointers to derived
|
||||
template<typename _Tp, typename... _Args, typename _Req
|
||||
= _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>,
|
||||
_CheckArgs<_Pack<_Args...>>>>
|
||||
result_type
|
||||
operator()(_Tp&& __object, _Args&&... __args) const
|
||||
{
|
||||
return _M_call(std::forward<_Tp>(__object), &__object,
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
// Handle reference wrappers
|
||||
template<typename _Tp, typename... _Args, typename _Req
|
||||
= _Require<is_base_of<_Class, _Tp>, typename _Traits::__lvalue,
|
||||
_CheckArgs<_Pack<_Args...>>>>
|
||||
result_type
|
||||
operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const
|
||||
{ return operator()(__ref.get(), std::forward<_Args>(__args)...); }
|
||||
|
||||
private:
|
||||
template<typename _Tp, typename... _Args>
|
||||
result_type
|
||||
_M_call(_Tp&& __object, const volatile _Class *,
|
||||
_Args&&... __args) const
|
||||
{
|
||||
return (std::forward<_Tp>(__object).*_M_pmf)
|
||||
(std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
result_type
|
||||
_M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
|
||||
{ return ((*__ptr).*_M_pmf)(std::forward<_Args>(__args)...); }
|
||||
|
||||
_Pmf _M_pmf;
|
||||
template<typename... _Args>
|
||||
auto
|
||||
operator()(_Args&&... __args) const
|
||||
noexcept(noexcept(std::__invoke(_M_pmf, forward<_Args>(__args)...)))
|
||||
-> decltype(std::__invoke(_M_pmf, forward<_Args>(__args)...))
|
||||
{ return std::__invoke(_M_pmf, std::forward<_Args>(__args)...); }
|
||||
};
|
||||
|
||||
// Partial specialization for member object pointers.
|
||||
template<typename _Res, typename _Class>
|
||||
class _Mem_fn_base<_Res _Class::*, false>
|
||||
template<typename _MemObjPtr>
|
||||
class _Mem_fn_base<_MemObjPtr, false>
|
||||
{
|
||||
using __pm_type = _Res _Class::*;
|
||||
|
||||
// This bit of genius is due to Peter Dimov, improved slightly by
|
||||
// Douglas Gregor.
|
||||
// Made less elegant to support perfect forwarding and noexcept.
|
||||
template<typename _Tp>
|
||||
auto
|
||||
_M_call(_Tp&& __object, const _Class *) const noexcept
|
||||
-> decltype(std::forward<_Tp>(__object).*std::declval<__pm_type&>())
|
||||
{ return std::forward<_Tp>(__object).*_M_pm; }
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
auto
|
||||
_M_call(_Tp&& __object, _Up * const *) const noexcept
|
||||
-> decltype((*std::forward<_Tp>(__object)).*std::declval<__pm_type&>())
|
||||
{ return (*std::forward<_Tp>(__object)).*_M_pm; }
|
||||
|
||||
template<typename _Tp>
|
||||
auto
|
||||
_M_call(_Tp&& __ptr, const volatile void*) const
|
||||
noexcept(noexcept((*__ptr).*std::declval<__pm_type&>()))
|
||||
-> decltype((*__ptr).*std::declval<__pm_type&>())
|
||||
{ return (*__ptr).*_M_pm; }
|
||||
|
||||
using _Arity = integral_constant<size_t, 0>;
|
||||
using _Varargs = false_type;
|
||||
|
||||
template<typename _Func, typename... _BoundArgs>
|
||||
friend struct _Bind_check_arity;
|
||||
|
||||
_MemObjPtr _M_pm;
|
||||
|
||||
public:
|
||||
explicit constexpr
|
||||
_Mem_fn_base(_Res _Class::*__pm) noexcept : _M_pm(__pm) { }
|
||||
_Mem_fn_base(_MemObjPtr __pm) noexcept : _M_pm(__pm) { }
|
||||
|
||||
// Handle objects
|
||||
_Res&
|
||||
operator()(_Class& __object) const noexcept
|
||||
{ return __object.*_M_pm; }
|
||||
|
||||
const _Res&
|
||||
operator()(const _Class& __object) const noexcept
|
||||
{ return __object.*_M_pm; }
|
||||
|
||||
_Res&&
|
||||
operator()(_Class&& __object) const noexcept
|
||||
{ return std::forward<_Class>(__object).*_M_pm; }
|
||||
|
||||
const _Res&&
|
||||
operator()(const _Class&& __object) const noexcept
|
||||
{ return std::forward<const _Class>(__object).*_M_pm; }
|
||||
|
||||
// Handle pointers
|
||||
_Res&
|
||||
operator()(_Class* __object) const noexcept
|
||||
{ return __object->*_M_pm; }
|
||||
|
||||
const _Res&
|
||||
operator()(const _Class* __object) const noexcept
|
||||
{ return __object->*_M_pm; }
|
||||
|
||||
// Handle smart pointers and derived
|
||||
template<typename _Tp, typename _Req = _Require<_NotSame<_Class*, _Tp>>>
|
||||
template<typename _Tp>
|
||||
auto
|
||||
operator()(_Tp&& __unknown) const
|
||||
noexcept(noexcept(std::declval<_Mem_fn_base*>()->_M_call
|
||||
(std::forward<_Tp>(__unknown), &__unknown)))
|
||||
-> decltype(this->_M_call(std::forward<_Tp>(__unknown), &__unknown))
|
||||
{ return _M_call(std::forward<_Tp>(__unknown), &__unknown); }
|
||||
|
||||
template<typename _Tp, typename _Req = _Require<is_base_of<_Class, _Tp>>>
|
||||
auto
|
||||
operator()(reference_wrapper<_Tp> __ref) const
|
||||
noexcept(noexcept(std::declval<_Mem_fn_base&>()(__ref.get())))
|
||||
-> decltype((*this)(__ref.get()))
|
||||
{ return (*this)(__ref.get()); }
|
||||
|
||||
private:
|
||||
_Res _Class::*_M_pm;
|
||||
operator()(_Tp&& __obj) const
|
||||
noexcept(noexcept(std::__invoke(_M_pm, forward<_Tp>(__obj))))
|
||||
-> decltype(std::__invoke(_M_pm, std::forward<_Tp>(__obj)))
|
||||
{ return std::__invoke(_M_pm, std::forward<_Tp>(__obj)); }
|
||||
};
|
||||
|
||||
template<typename _Res, typename _Class>
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue