mirror of git://gcc.gnu.org/git/gcc.git
functional (_Mem_fn): Constrain function call operators to avoid ambiguities.
* include/std/functional (_Mem_fn): Constrain function call operators to avoid ambiguities. Use perfect forwarding. * testsuite/20_util/function_objects/mem_fn/55463.cc: Additional tests. * testsuite/20_util/function_objects/mem_fn/forward.cc: New. * testsuite/20_util/bind/ref_neg.cc: Adjust dg-error line numbers. From-SVN: r193879
This commit is contained in:
parent
69bccd4a33
commit
b1c2b51b66
|
|
@ -1,3 +1,12 @@
|
||||||
|
2012-11-28 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||||
|
|
||||||
|
* include/std/functional (_Mem_fn): Constrain function call operators
|
||||||
|
to avoid ambiguities. Use perfect forwarding.
|
||||||
|
* testsuite/20_util/function_objects/mem_fn/55463.cc: Additional
|
||||||
|
tests.
|
||||||
|
* testsuite/20_util/function_objects/mem_fn/forward.cc: New.
|
||||||
|
* testsuite/20_util/bind/ref_neg.cc: Adjust dg-error line numbers.
|
||||||
|
|
||||||
2012-11-27 Ollie Wild <aaw@google.com>
|
2012-11-27 Ollie Wild <aaw@google.com>
|
||||||
|
|
||||||
* include/bits/stl_tree.h (@headername): Fix incorrect Doxygen macro
|
* include/bits/stl_tree.h (@headername): Fix incorrect Doxygen macro
|
||||||
|
|
|
||||||
|
|
@ -501,6 +501,26 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
|
|
||||||
// @} group functors
|
// @} group functors
|
||||||
|
|
||||||
|
template<typename... _Cond>
|
||||||
|
using _Require = typename enable_if<__and_<_Cond...>::value>::type;
|
||||||
|
|
||||||
|
template<typename... _Types>
|
||||||
|
struct _Pack : integral_constant<size_t, sizeof...(_Types)>
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename _From, typename _To, bool = _From::value == _To::value>
|
||||||
|
struct _AllConvertible : false_type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename... _From, typename... _To>
|
||||||
|
struct _AllConvertible<_Pack<_From...>, _Pack<_To...>, true>
|
||||||
|
: __and_<is_convertible<_From, _To>...>
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename _Tp1, typename _Tp2>
|
||||||
|
using _NotSame = __not_<is_same<typename std::decay<_Tp1>::type,
|
||||||
|
typename std::decay<_Tp2>::type>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derives from @c unary_function or @c binary_function, or perhaps
|
* Derives from @c unary_function or @c binary_function, or perhaps
|
||||||
* nothing, depending on the number of arguments provided. The
|
* nothing, depending on the number of arguments provided. The
|
||||||
|
|
@ -526,19 +546,38 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
{
|
{
|
||||||
typedef _Res (_Class::*_Functor)(_ArgTypes...);
|
typedef _Res (_Class::*_Functor)(_ArgTypes...);
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __object, const volatile _Class *,
|
_M_call(_Tp&& __object, const volatile _Class *,
|
||||||
_ArgTypes... __args) const
|
_Args&&... __args) const
|
||||||
{
|
{
|
||||||
return (std::forward<_Tp>(__object).*__pmf)
|
return (std::forward<_Tp>(__object).*__pmf)
|
||||||
(std::forward<_ArgTypes>(__args)...);
|
(std::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const
|
_M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
|
||||||
{ return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
{ return ((*__ptr).*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
// Require each _Args to be convertible to corresponding _ArgTypes
|
||||||
|
template<typename... _Args>
|
||||||
|
using _RequireValidArgs
|
||||||
|
= _Require<_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
// Require each _Args to be convertible to corresponding _ArgTypes
|
||||||
|
// and require _Tp is not _Class, _Class& or _Class*
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs2
|
||||||
|
= _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
// Require each _Args to be convertible to corresponding _ArgTypes
|
||||||
|
// and require _Tp is _Class or derived from _Class
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs3
|
||||||
|
= _Require<is_base_of<_Class, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Res result_type;
|
typedef _Res result_type;
|
||||||
|
|
@ -546,28 +585,39 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
||||||
|
|
||||||
// Handle objects
|
// Handle objects
|
||||||
_Res
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
operator()(_Class& __object, _ArgTypes... __args) const
|
|
||||||
{ return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
|
||||||
|
|
||||||
// Handle pointers
|
|
||||||
_Res
|
|
||||||
operator()(_Class* __object, _ArgTypes... __args) const
|
|
||||||
{ return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
|
||||||
|
|
||||||
// Handle smart pointers, references and pointers to derived
|
|
||||||
template<typename _Tp>
|
|
||||||
_Res
|
_Res
|
||||||
operator()(_Tp&& __object, _ArgTypes... __args) const
|
operator()(_Class& __object, _Args&&... __args) const
|
||||||
|
{ return (__object.*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(_Class&& __object, _Args&&... __args) const
|
||||||
{
|
{
|
||||||
return _M_call(std::forward<_Tp>(__object), &__object,
|
return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
|
||||||
std::forward<_ArgTypes>(__args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
// Handle pointers
|
||||||
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
_Res
|
_Res
|
||||||
operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const
|
operator()(_Class* __object, _Args&&... __args) const
|
||||||
{ return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); }
|
{ return (__object->*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
// Handle smart pointers, references and pointers to derived
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs2<_Tp, _Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(_Tp&& __object, _Args&&... __args) const
|
||||||
|
{
|
||||||
|
return _M_call(std::forward<_Tp>(__object), &__object,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs3<_Tp, _Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const
|
||||||
|
{ return operator()(__ref.get(), std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_Functor __pmf;
|
_Functor __pmf;
|
||||||
|
|
@ -581,19 +631,33 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
{
|
{
|
||||||
typedef _Res (_Class::*_Functor)(_ArgTypes...) const;
|
typedef _Res (_Class::*_Functor)(_ArgTypes...) const;
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __object, const volatile _Class *,
|
_M_call(_Tp&& __object, const volatile _Class *,
|
||||||
_ArgTypes... __args) const
|
_Args&&... __args) const
|
||||||
{
|
{
|
||||||
return (std::forward<_Tp>(__object).*__pmf)
|
return (std::forward<_Tp>(__object).*__pmf)
|
||||||
(std::forward<_ArgTypes>(__args)...);
|
(std::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const
|
_M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
|
||||||
{ return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
{ return ((*__ptr).*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
template<typename... _Args>
|
||||||
|
using _RequireValidArgs
|
||||||
|
= _Require<_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs2
|
||||||
|
= _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs3
|
||||||
|
= _Require<is_base_of<_Class, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Res result_type;
|
typedef _Res result_type;
|
||||||
|
|
@ -601,27 +665,38 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
||||||
|
|
||||||
// Handle objects
|
// Handle objects
|
||||||
_Res
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
operator()(const _Class& __object, _ArgTypes... __args) const
|
_Res
|
||||||
{ return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
operator()(const _Class& __object, _Args&&... __args) const
|
||||||
|
{ return (__object.*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
// Handle pointers
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
_Res
|
_Res
|
||||||
operator()(const _Class* __object, _ArgTypes... __args) const
|
operator()(const _Class&& __object, _Args&&... __args) const
|
||||||
{ return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
|
||||||
|
|
||||||
// Handle smart pointers, references and pointers to derived
|
|
||||||
template<typename _Tp>
|
|
||||||
_Res operator()(_Tp&& __object, _ArgTypes... __args) const
|
|
||||||
{
|
{
|
||||||
return _M_call(std::forward<_Tp>(__object), &__object,
|
return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
|
||||||
std::forward<_ArgTypes>(__args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
// Handle pointers
|
||||||
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
_Res
|
_Res
|
||||||
operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const
|
operator()(const _Class* __object, _Args&&... __args) const
|
||||||
{ return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); }
|
{ return (__object->*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
// Handle smart pointers, references and pointers to derived
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs2<_Tp, _Args...>>
|
||||||
|
_Res operator()(_Tp&& __object, _Args&&... __args) const
|
||||||
|
{
|
||||||
|
return _M_call(std::forward<_Tp>(__object), &__object,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs3<_Tp, _Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const
|
||||||
|
{ return operator()(__ref.get(), std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_Functor __pmf;
|
_Functor __pmf;
|
||||||
|
|
@ -635,19 +710,33 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
{
|
{
|
||||||
typedef _Res (_Class::*_Functor)(_ArgTypes...) volatile;
|
typedef _Res (_Class::*_Functor)(_ArgTypes...) volatile;
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __object, const volatile _Class *,
|
_M_call(_Tp&& __object, const volatile _Class *,
|
||||||
_ArgTypes... __args) const
|
_Args&&... __args) const
|
||||||
{
|
{
|
||||||
return (std::forward<_Tp>(__object).*__pmf)
|
return (std::forward<_Tp>(__object).*__pmf)
|
||||||
(std::forward<_ArgTypes>(__args)...);
|
(std::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const
|
_M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
|
||||||
{ return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
{ return ((*__ptr).*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
template<typename... _Args>
|
||||||
|
using _RequireValidArgs
|
||||||
|
= _Require<_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs2
|
||||||
|
= _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs3
|
||||||
|
= _Require<is_base_of<_Class, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Res result_type;
|
typedef _Res result_type;
|
||||||
|
|
@ -655,28 +744,39 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
||||||
|
|
||||||
// Handle objects
|
// Handle objects
|
||||||
_Res
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
operator()(volatile _Class& __object, _ArgTypes... __args) const
|
|
||||||
{ return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
|
||||||
|
|
||||||
// Handle pointers
|
|
||||||
_Res
|
|
||||||
operator()(volatile _Class* __object, _ArgTypes... __args) const
|
|
||||||
{ return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
|
||||||
|
|
||||||
// Handle smart pointers, references and pointers to derived
|
|
||||||
template<typename _Tp>
|
|
||||||
_Res
|
_Res
|
||||||
operator()(_Tp&& __object, _ArgTypes... __args) const
|
operator()(volatile _Class& __object, _Args&&... __args) const
|
||||||
|
{ return (__object.*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(volatile _Class&& __object, _Args&&... __args) const
|
||||||
{
|
{
|
||||||
return _M_call(std::forward<_Tp>(__object), &__object,
|
return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
|
||||||
std::forward<_ArgTypes>(__args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
// Handle pointers
|
||||||
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
_Res
|
_Res
|
||||||
operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const
|
operator()(volatile _Class* __object, _Args&&... __args) const
|
||||||
{ return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); }
|
{ return (__object->*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
// Handle smart pointers, references and pointers to derived
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs2<_Tp, _Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(_Tp&& __object, _Args&&... __args) const
|
||||||
|
{
|
||||||
|
return _M_call(std::forward<_Tp>(__object), &__object,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs3<_Tp, _Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const
|
||||||
|
{ return operator()(__ref.get(), std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_Functor __pmf;
|
_Functor __pmf;
|
||||||
|
|
@ -690,19 +790,33 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
{
|
{
|
||||||
typedef _Res (_Class::*_Functor)(_ArgTypes...) const volatile;
|
typedef _Res (_Class::*_Functor)(_ArgTypes...) const volatile;
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __object, const volatile _Class *,
|
_M_call(_Tp&& __object, const volatile _Class *,
|
||||||
_ArgTypes... __args) const
|
_Args&&... __args) const
|
||||||
{
|
{
|
||||||
return (std::forward<_Tp>(__object).*__pmf)
|
return (std::forward<_Tp>(__object).*__pmf)
|
||||||
(std::forward<_ArgTypes>(__args)...);
|
(std::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename... _Args>
|
||||||
_Res
|
_Res
|
||||||
_M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const
|
_M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
|
||||||
{ return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
{ return ((*__ptr).*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
template<typename... _Args>
|
||||||
|
using _RequireValidArgs
|
||||||
|
= _Require<_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs2
|
||||||
|
= _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args>
|
||||||
|
using _RequireValidArgs3
|
||||||
|
= _Require<is_base_of<_Class, _Tp>,
|
||||||
|
_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Res result_type;
|
typedef _Res result_type;
|
||||||
|
|
@ -710,27 +824,38 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
|
||||||
|
|
||||||
// Handle objects
|
// Handle objects
|
||||||
_Res
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
operator()(const volatile _Class& __object, _ArgTypes... __args) const
|
_Res
|
||||||
{ return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
operator()(const volatile _Class& __object, _Args&&... __args) const
|
||||||
|
{ return (__object.*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
// Handle pointers
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
_Res
|
_Res
|
||||||
operator()(const volatile _Class* __object, _ArgTypes... __args) const
|
operator()(const volatile _Class&& __object, _Args&&... __args) const
|
||||||
{ return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); }
|
|
||||||
|
|
||||||
// Handle smart pointers, references and pointers to derived
|
|
||||||
template<typename _Tp>
|
|
||||||
_Res operator()(_Tp&& __object, _ArgTypes... __args) const
|
|
||||||
{
|
{
|
||||||
return _M_call(std::forward<_Tp>(__object), &__object,
|
return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
|
||||||
std::forward<_ArgTypes>(__args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp>
|
// Handle pointers
|
||||||
|
template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
|
||||||
_Res
|
_Res
|
||||||
operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const
|
operator()(const volatile _Class* __object, _Args&&... __args) const
|
||||||
{ return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); }
|
{ return (__object->*__pmf)(std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
|
// Handle smart pointers, references and pointers to derived
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs2<_Tp, _Args...>>
|
||||||
|
_Res operator()(_Tp&& __object, _Args&&... __args) const
|
||||||
|
{
|
||||||
|
return _M_call(std::forward<_Tp>(__object), &__object,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp, typename... _Args,
|
||||||
|
typename _Req = _RequireValidArgs3<_Tp, _Args...>>
|
||||||
|
_Res
|
||||||
|
operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const
|
||||||
|
{ return operator()(__ref.get(), std::forward<_Args>(__args)...); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_Functor __pmf;
|
_Functor __pmf;
|
||||||
|
|
@ -756,7 +881,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
|
|
||||||
// This bit of genius is due to Peter Dimov, improved slightly by
|
// This bit of genius is due to Peter Dimov, improved slightly by
|
||||||
// Douglas Gregor.
|
// Douglas Gregor.
|
||||||
// Made less elegant by Jonathan Wakely to support perfect forwarding.
|
// Made less elegant to support perfect forwarding and noexcept.
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
auto
|
auto
|
||||||
_M_call(_Tp&& __object, const _Class *) const noexcept
|
_M_call(_Tp&& __object, const _Class *) const noexcept
|
||||||
|
|
@ -807,7 +932,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
{ return __object->*__pm; }
|
{ return __object->*__pm; }
|
||||||
|
|
||||||
// Handle smart pointers and derived
|
// Handle smart pointers and derived
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename _Req = _Require<_NotSame<_Class*, _Tp>>>
|
||||||
auto
|
auto
|
||||||
operator()(_Tp&& __unknown) const
|
operator()(_Tp&& __unknown) const
|
||||||
noexcept(noexcept(std::declval<_Mem_fn*>()->_M_call
|
noexcept(noexcept(std::declval<_Mem_fn*>()->_M_call
|
||||||
|
|
@ -815,12 +940,12 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
|
||||||
-> decltype(this->_M_call(std::forward<_Tp>(__unknown), &__unknown))
|
-> decltype(this->_M_call(std::forward<_Tp>(__unknown), &__unknown))
|
||||||
{ return _M_call(std::forward<_Tp>(__unknown), &__unknown); }
|
{ return _M_call(std::forward<_Tp>(__unknown), &__unknown); }
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp, typename _Req = _Require<is_base_of<_Class, _Tp>>>
|
||||||
auto
|
auto
|
||||||
operator()(reference_wrapper<_Tp> __ref) const
|
operator()(reference_wrapper<_Tp> __ref) const
|
||||||
noexcept(noexcept(std::declval<_Mem_fn&>()(__ref.get())))
|
noexcept(noexcept(std::declval<_Mem_fn&>()(__ref.get())))
|
||||||
-> decltype((*this)(__ref.get()))
|
-> decltype((*this)(__ref.get()))
|
||||||
{ return operator()(__ref.get()); }
|
{ return (*this)(__ref.get()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_Res _Class::*__pm;
|
_Res _Class::*__pm;
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,10 @@ void test01()
|
||||||
{
|
{
|
||||||
const int dummy = 0;
|
const int dummy = 0;
|
||||||
std::bind(&inc, _1)(0); // { dg-error "no match" }
|
std::bind(&inc, _1)(0); // { dg-error "no match" }
|
||||||
// { dg-error "rvalue|const" "" { target *-*-* } 1224 }
|
// { dg-error "rvalue|const" "" { target *-*-* } 1349 }
|
||||||
// { dg-error "rvalue|const" "" { target *-*-* } 1238 }
|
// { dg-error "rvalue|const" "" { target *-*-* } 1363 }
|
||||||
// { dg-error "rvalue|const" "" { target *-*-* } 1252 }
|
// { dg-error "rvalue|const" "" { target *-*-* } 1377 }
|
||||||
// { dg-error "rvalue|const" "" { target *-*-* } 1266 }
|
// { dg-error "rvalue|const" "" { target *-*-* } 1391 }
|
||||||
std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" }
|
std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,12 @@ struct X
|
||||||
int data;
|
int data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Y : X { };
|
||||||
|
|
||||||
using CX = const X;
|
using CX = const X;
|
||||||
|
using CY = const Y;
|
||||||
|
|
||||||
|
using X_ptr = X*;
|
||||||
|
|
||||||
struct smart_ptr
|
struct smart_ptr
|
||||||
{
|
{
|
||||||
|
|
@ -41,38 +46,63 @@ struct smart_ptr
|
||||||
|
|
||||||
std::reference_wrapper<X> ref();
|
std::reference_wrapper<X> ref();
|
||||||
std::reference_wrapper<const X> cref();
|
std::reference_wrapper<const X> cref();
|
||||||
|
std::reference_wrapper<Y> yref();
|
||||||
|
|
||||||
void test01()
|
void test01()
|
||||||
{
|
{
|
||||||
int& i1 = std::mem_fn( &X::func )( X() );
|
int& i1 = std::mem_fn( &X::func )( X() );
|
||||||
int& i2 = std::mem_fn( &X::func )( smart_ptr() );
|
int& i2 = std::mem_fn( &X::func )( Y() );
|
||||||
int& i3 = std::mem_fn( &X::func )( ref() );
|
int& i3 = std::mem_fn( &X::func )( ref() );
|
||||||
|
int& i4 = std::mem_fn( &X::func )( yref() );
|
||||||
|
int& i5 = std::mem_fn( &X::func )( X_ptr() );
|
||||||
|
int& i6 = std::mem_fn( &X::func )( smart_ptr() );
|
||||||
|
|
||||||
char& c1 = std::mem_fn( &X::func_c )( X() );
|
char& c1 = std::mem_fn( &X::func_c )( X() );
|
||||||
char& c2 = std::mem_fn( &X::func_c )( CX() );
|
char& c2 = std::mem_fn( &X::func_c )( CX() );
|
||||||
char& c3 = std::mem_fn( &X::func_c )( smart_ptr() );
|
char& c3 = std::mem_fn( &X::func_c )( Y() );
|
||||||
char& c4 = std::mem_fn( &X::func_c )( ref() );
|
char& c4 = std::mem_fn( &X::func_c )( ref() );
|
||||||
char& c5 = std::mem_fn( &X::func_c )( cref() );
|
char& c5 = std::mem_fn( &X::func_c )( cref() );
|
||||||
|
char& c6 = std::mem_fn( &X::func_c )( yref() );
|
||||||
|
char& c7 = std::mem_fn( &X::func_c )( X_ptr() );
|
||||||
|
char& c8 = std::mem_fn( &X::func_c )( smart_ptr() );
|
||||||
|
|
||||||
short& s1 = std::mem_fn( &X::func_v )( X() );
|
short& s1 = std::mem_fn( &X::func_v )( X() );
|
||||||
short& s2 = std::mem_fn( &X::func_v )( smart_ptr() );
|
short& s2 = std::mem_fn( &X::func_v )( Y() );
|
||||||
short& s3 = std::mem_fn( &X::func_v )( ref() );
|
short& s3 = std::mem_fn( &X::func_v )( ref() );
|
||||||
|
short& s4 = std::mem_fn( &X::func_v )( yref() );
|
||||||
|
short& s5 = std::mem_fn( &X::func_v )( X_ptr() );
|
||||||
|
short& s6 = std::mem_fn( &X::func_v )( smart_ptr() );
|
||||||
|
|
||||||
double& d1 = std::mem_fn( &X::func_cv )( X() );
|
double& d1 = std::mem_fn( &X::func_cv )( X() );
|
||||||
double& d2 = std::mem_fn( &X::func_cv )( CX() );
|
double& d2 = std::mem_fn( &X::func_cv )( CX() );
|
||||||
double& d3 = std::mem_fn( &X::func_cv )( smart_ptr() );
|
double& d3 = std::mem_fn( &X::func_cv )( Y() );
|
||||||
double& d4 = std::mem_fn( &X::func_cv )( ref() );
|
double& d4 = std::mem_fn( &X::func_cv )( ref() );
|
||||||
double& d5 = std::mem_fn( &X::func_cv )( cref() );
|
double& d5 = std::mem_fn( &X::func_cv )( cref() );
|
||||||
|
double& d6 = std::mem_fn( &X::func_cv )( yref() );
|
||||||
|
double& d7 = std::mem_fn( &X::func_cv )( X_ptr() );
|
||||||
|
double& d8 = std::mem_fn( &X::func_cv )( smart_ptr() );
|
||||||
|
|
||||||
// [expr.mptr.oper]
|
// [expr.mptr.oper]
|
||||||
// The result of a .* expression whose second operand is a pointer to a
|
// The result of a .* expression whose second operand is a pointer to a
|
||||||
// data member is of the same value category (3.10) as its first operand.
|
// data member is of the same value category (3.10) as its first operand.
|
||||||
int&& rval = std::mem_fn( &X::data )( X() );
|
int&& rval = std::mem_fn( &X::data )( X() );
|
||||||
const int&& crval = std::mem_fn( &X::data )( CX() );
|
const int&& crval = std::mem_fn( &X::data )( CX() );
|
||||||
|
int&& yrval = std::mem_fn( &X::data )( Y() );
|
||||||
int& sval = std::mem_fn( &X::data )( smart_ptr() );
|
const int&& ycrval = std::mem_fn( &X::data )( CY() );
|
||||||
|
|
||||||
int& val = std::mem_fn( &X::data )( ref() );
|
int& val = std::mem_fn( &X::data )( ref() );
|
||||||
const int& cval = std::mem_fn( &X::data )( cref() );
|
const int& cval = std::mem_fn( &X::data )( cref() );
|
||||||
|
int& yval = std::mem_fn( &X::data )( yref() );
|
||||||
|
|
||||||
|
int& pval = std::mem_fn( &X::data )( X_ptr() );
|
||||||
|
int& sval = std::mem_fn( &X::data )( smart_ptr() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test02()
|
||||||
|
{
|
||||||
|
std::reference_wrapper<X> r = ref();
|
||||||
|
X& x1 = std::mem_fn( &std::reference_wrapper<X>::get )( r );
|
||||||
|
const std::reference_wrapper<X> cr = ref();
|
||||||
|
const X& x3 = std::mem_fn( &std::reference_wrapper<X>::get )( cr );
|
||||||
|
X& x2 = std::mem_fn( &std::reference_wrapper<X>::get )( ref() );
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
|
// Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
|
struct Counter
|
||||||
|
{
|
||||||
|
Counter() = default;
|
||||||
|
Counter(const Counter&) { ++count; }
|
||||||
|
|
||||||
|
static int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
int Counter::count = 0;
|
||||||
|
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
int func(Counter, int i) { return i; }
|
||||||
|
char func_c(Counter, char c) const { return c; }
|
||||||
|
short func_v(Counter, short s) volatile { return s; }
|
||||||
|
double func_cv(Counter, double d) const volatile { return d; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void test01()
|
||||||
|
{
|
||||||
|
Counter c;
|
||||||
|
X x;
|
||||||
|
|
||||||
|
std::mem_fn( &X::func )( x, c, 0 );
|
||||||
|
VERIFY( Counter::count == 1 );
|
||||||
|
|
||||||
|
std::mem_fn( &X::func_c )( x, c, 0 );
|
||||||
|
VERIFY( Counter::count == 2 );
|
||||||
|
|
||||||
|
std::mem_fn( &X::func_v )( x, c, 0 );
|
||||||
|
VERIFY( Counter::count == 3 );
|
||||||
|
|
||||||
|
std::mem_fn( &X::func_cv )( x, c, 0 );
|
||||||
|
VERIFY( Counter::count == 4 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue