* [patch] libstdc++/57898 add ref-qualifier support to std::mem_fn
@ 2014-11-03 2:56 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2014-11-03 2:56 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 251 bytes --]
Two patches, the first rewrites std::mem_fn to support ref-qualifiers
(without tons of code duplication) and the second adds some static
assertions to reject invalid bind expressions earlier (at "bind time")
Tested x86_64-linux, committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 24758 bytes --]
commit 5ab949c9590fc837118f8ad6d0facc3f8bd2cc07
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date: Wed Nov 28 00:58:58 2012 +0000
Add support for ref-qualified functions to std::mem_fn
PR libstdc++/57898
* include/std/functional (_Mem_fn_traits_base): New class template.
(_Mem_fn_traits): New class template with specializations for every
combination of cv-qualified and ref-qualified member function.
(_Mem_fn_base): New class template for all pointer to member function
types and partial specialization for pointer to member object types.
(_Mem_fn): Inherit from _Mem_fn_base.
* testsuite/20_util/function_objects/mem_fn/refqual.cc: New.
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 5bc2730..ecc5bc9 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -504,344 +504,231 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
struct _Maybe_unary_or_binary_function<_Res, _T1, _T2>
: std::binary_function<_T1, _T2, _Res> { };
- /// Implementation of @c mem_fn for member function pointers.
+ template<typename _Signature>
+ struct _Mem_fn_traits;
+
template<typename _Res, typename _Class, typename... _ArgTypes>
- class _Mem_fn<_Res (_Class::*)(_ArgTypes...)>
- : public _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>
+ struct _Mem_fn_traits_base
{
- typedef _Res (_Class::*_Functor)(_ArgTypes...);
-
- template<typename _Tp, typename... _Args>
- _Res
- _M_call(_Tp&& __object, const volatile _Class *,
- _Args&&... __args) const
- {
- return (std::forward<_Tp>(__object).*__pmf)
- (std::forward<_Args>(__args)...);
- }
-
- template<typename _Tp, typename... _Args>
- _Res
- _M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
- { 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:
- typedef _Res result_type;
-
- explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
-
- // Handle objects
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- 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 (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
- }
-
- // Handle pointers
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(_Class* __object, _Args&&... __args) const
- { 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:
- _Functor __pmf;
+ using __result_type = _Res;
+ using __class_type = _Class;
+ using __arg_types = _Pack<_ArgTypes...>;
+ using __maybe_type
+ = _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>;
};
- /// Implementation of @c mem_fn for const member function pointers.
template<typename _Res, typename _Class, typename... _ArgTypes>
- class _Mem_fn<_Res (_Class::*)(_ArgTypes...) const>
- : public _Maybe_unary_or_binary_function<_Res, const _Class*,
- _ArgTypes...>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...)>
+ : _Mem_fn_traits_base<_Res, _Class, _ArgTypes...>
{
- typedef _Res (_Class::*_Functor)(_ArgTypes...) const;
-
- template<typename _Tp, typename... _Args>
- _Res
- _M_call(_Tp&& __object, const volatile _Class *,
- _Args&&... __args) const
- {
- return (std::forward<_Tp>(__object).*__pmf)
- (std::forward<_Args>(__args)...);
- }
-
- template<typename _Tp, typename... _Args>
- _Res
- _M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
- { 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<const _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:
- typedef _Res result_type;
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...);
+ using __lvalue = true_type;
+ using __rvalue = true_type;
+ };
- explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const>
+ : _Mem_fn_traits_base<_Res, const _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) const;
+ using __lvalue = true_type;
+ using __rvalue = true_type;
+ };
- // Handle objects
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(const _Class& __object, _Args&&... __args) const
- { return (__object.*__pmf)(std::forward<_Args>(__args)...); }
-
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(const _Class&& __object, _Args&&... __args) const
- {
- return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
- }
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) volatile>
+ : _Mem_fn_traits_base<_Res, volatile _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) volatile;
+ using __lvalue = true_type;
+ using __rvalue = true_type;
+ };
- // Handle pointers
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(const _Class* __object, _Args&&... __args) const
- { return (__object->*__pmf)(std::forward<_Args>(__args)...); }
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const volatile>
+ : _Mem_fn_traits_base<_Res, const volatile _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) const volatile;
+ using __lvalue = true_type;
+ using __rvalue = true_type;
+ };
- // 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 _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...)&>
+ : _Mem_fn_traits_base<_Res, _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...)&;
+ using __lvalue = true_type;
+ using __rvalue = false_type;
+ };
- 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)...); }
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const&>
+ : _Mem_fn_traits_base<_Res, const _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) const&;
+ using __lvalue = true_type;
+ using __rvalue = false_type;
+ };
- private:
- _Functor __pmf;
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) volatile&>
+ : _Mem_fn_traits_base<_Res, volatile _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) volatile&;
+ using __lvalue = true_type;
+ using __rvalue = false_type;
};
- /// Implementation of @c mem_fn for volatile member function pointers.
template<typename _Res, typename _Class, typename... _ArgTypes>
- class _Mem_fn<_Res (_Class::*)(_ArgTypes...) volatile>
- : public _Maybe_unary_or_binary_function<_Res, volatile _Class*,
- _ArgTypes...>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const volatile&>
+ : _Mem_fn_traits_base<_Res, const volatile _Class, _ArgTypes...>
{
- typedef _Res (_Class::*_Functor)(_ArgTypes...) volatile;
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) const volatile&;
+ using __lvalue = true_type;
+ using __rvalue = false_type;
+ };
- template<typename _Tp, typename... _Args>
- _Res
- _M_call(_Tp&& __object, const volatile _Class *,
- _Args&&... __args) const
- {
- return (std::forward<_Tp>(__object).*__pmf)
- (std::forward<_Args>(__args)...);
- }
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...)&&>
+ : _Mem_fn_traits_base<_Res, _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...)&&;
+ using __lvalue = false_type;
+ using __rvalue = true_type;
+ };
- template<typename _Tp, typename... _Args>
- _Res
- _M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
- { return ((*__ptr).*__pmf)(std::forward<_Args>(__args)...); }
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const&&>
+ : _Mem_fn_traits_base<_Res, const _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) const&&;
+ using __lvalue = false_type;
+ using __rvalue = true_type;
+ };
- template<typename... _Args>
- using _RequireValidArgs
- = _Require<_AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) volatile&&>
+ : _Mem_fn_traits_base<_Res, volatile _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) volatile&&;
+ using __lvalue = false_type;
+ using __rvalue = true_type;
+ };
- template<typename _Tp, typename... _Args>
- using _RequireValidArgs2
- = _Require<_NotSame<_Class, _Tp>, _NotSame<volatile _Class*, _Tp>,
- _AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
+ template<typename _Res, typename _Class, typename... _ArgTypes>
+ struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) const volatile&&>
+ : _Mem_fn_traits_base<_Res, const volatile _Class, _ArgTypes...>
+ {
+ using __pmf_type = _Res (_Class::*)(_ArgTypes...) const volatile&&;
+ using __lvalue = false_type;
+ using __rvalue = true_type;
+ };
- template<typename _Tp, typename... _Args>
- using _RequireValidArgs3
- = _Require<is_base_of<_Class, _Tp>,
- _AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
+ template<typename _MemFunPtr,
+ bool __is_mem_fn = is_member_function_pointer<_MemFunPtr>::value>
+ class _Mem_fn_base
+ : public _Mem_fn_traits<_MemFunPtr>::__maybe_type
+ {
+ using _Traits = _Mem_fn_traits<_MemFunPtr>;
public:
- typedef _Res result_type;
-
- explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
-
- // Handle objects
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- 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 (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
- }
-
- // Handle pointers
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(volatile _Class* __object, _Args&&... __args) const
- { 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)...); }
+ using result_type = typename _Traits::__result_type;
private:
- _Functor __pmf;
- };
-
- /// Implementation of @c mem_fn for const volatile member function pointers.
- template<typename _Res, typename _Class, typename... _ArgTypes>
- class _Mem_fn<_Res (_Class::*)(_ArgTypes...) const volatile>
- : public _Maybe_unary_or_binary_function<_Res, const volatile _Class*,
- _ArgTypes...>
- {
- typedef _Res (_Class::*_Functor)(_ArgTypes...) const volatile;
+ using _Class = typename _Traits::__class_type;
+ using _ArgTypes = typename _Traits::__arg_types;
+ using _Pmf = typename _Traits::__pmf_type;
template<typename _Tp, typename... _Args>
- _Res
+ result_type
_M_call(_Tp&& __object, const volatile _Class *,
_Args&&... __args) const
{
- return (std::forward<_Tp>(__object).*__pmf)
+ return (std::forward<_Tp>(__object).*_M_pmf)
(std::forward<_Args>(__args)...);
}
template<typename _Tp, typename... _Args>
- _Res
+ result_type
_M_call(_Tp&& __ptr, const volatile void *, _Args&&... __args) const
- { return ((*__ptr).*__pmf)(std::forward<_Args>(__args)...); }
+ { return ((*__ptr).*_M_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<_AllConvertible<_Pack<_Args...>, _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<const volatile _Class*, _Tp>,
- _AllConvertible<_Pack<_Args...>, _Pack<_ArgTypes...>>>;
+ = _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>,
+ _AllConvertible<_Pack<_Args...>, _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...>>>;
+ _AllConvertible<_Pack<_Args...>, _ArgTypes>>;
public:
- typedef _Res result_type;
-
- explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { }
+ explicit _Mem_fn_base(_Pmf __pmf) : _M_pmf(__pmf) { }
// Handle objects
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(const volatile _Class& __object, _Args&&... __args) const
- { return (__object.*__pmf)(std::forward<_Args>(__args)...); }
-
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(const volatile _Class&& __object, _Args&&... __args) const
+ template<typename... _Args, typename _Req
+ = _Require<typename _Traits::__lvalue,
+ _AllConvertible<_Pack<_Args...>, _ArgTypes>>>
+ 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,
+ _AllConvertible<_Pack<_Args...>, _ArgTypes>>>
+ result_type
+ operator()(_Class&& __object, _Args&&... __args) const
{
- return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
+ return (std::move(__object).*_M_pmf)(std::forward<_Args>(__args)...);
}
// Handle pointers
- template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>>
- _Res
- operator()(const volatile _Class* __object, _Args&&... __args) const
- { return (__object->*__pmf)(std::forward<_Args>(__args)...); }
+ template<typename... _Args, typename _Req
+ = _Require<typename _Traits::__lvalue,
+ _AllConvertible<_Pack<_Args...>, _ArgTypes>>>
+ 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 = _RequireValidArgs2<_Tp, _Args...>>
- _Res operator()(_Tp&& __object, _Args&&... __args) const
+ // TODO how to constrain to lvalue/rvalue here? constrain _M_call?
+ template<typename _Tp, typename... _Args, typename _Req
+ = _Require<_NotSame<_Class, _Tp>, _NotSame<_Class*, _Tp>,
+ _AllConvertible<_Pack<_Args...>, _ArgTypes>>>
+ result_type
+ 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
+ // Handle reference wrappers
+ template<typename _Tp, typename... _Args, typename _Req
+ = _Require<is_base_of<_Class, _Tp>,
+ typename _Traits::__lvalue,
+ _AllConvertible<_Pack<_Args...>, _ArgTypes>>>
+ result_type
operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const
{ return operator()(__ref.get(), std::forward<_Args>(__args)...); }
private:
- _Functor __pmf;
- };
-
-
- template<typename _Tp, bool>
- struct _Mem_fn_const_or_non
- {
- typedef const _Tp& type;
- };
-
- template<typename _Tp>
- struct _Mem_fn_const_or_non<_Tp, false>
- {
- typedef _Tp& type;
+ _Pmf _M_pmf;
};
+ // Partial specialization for member object pointers.
template<typename _Res, typename _Class>
- class _Mem_fn<_Res _Class::*>
+ class _Mem_fn_base<_Res _Class::*, false>
{
using __pm_type = _Res _Class::*;
@@ -852,56 +739,56 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
auto
_M_call(_Tp&& __object, const _Class *) const noexcept
-> decltype(std::forward<_Tp>(__object).*std::declval<__pm_type&>())
- { return std::forward<_Tp>(__object).*__pm; }
+ { 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)).*__pm; }
+ { 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).*__pm; }
+ { return (*__ptr).*_M_pm; }
public:
explicit
- _Mem_fn(_Res _Class::*__pm) noexcept : __pm(__pm) { }
+ _Mem_fn_base(_Res _Class::*__pm) noexcept : _M_pm(__pm) { }
// Handle objects
_Res&
operator()(_Class& __object) const noexcept
- { return __object.*__pm; }
+ { return __object.*_M_pm; }
const _Res&
operator()(const _Class& __object) const noexcept
- { return __object.*__pm; }
+ { return __object.*_M_pm; }
_Res&&
operator()(_Class&& __object) const noexcept
- { return std::forward<_Class>(__object).*__pm; }
+ { return std::forward<_Class>(__object).*_M_pm; }
const _Res&&
operator()(const _Class&& __object) const noexcept
- { return std::forward<const _Class>(__object).*__pm; }
+ { return std::forward<const _Class>(__object).*_M_pm; }
// Handle pointers
_Res&
operator()(_Class* __object) const noexcept
- { return __object->*__pm; }
+ { return __object->*_M_pm; }
const _Res&
operator()(const _Class* __object) const noexcept
- { return __object->*__pm; }
+ { return __object->*_M_pm; }
// Handle smart pointers and derived
template<typename _Tp, typename _Req = _Require<_NotSame<_Class*, _Tp>>>
auto
operator()(_Tp&& __unknown) const
- noexcept(noexcept(std::declval<_Mem_fn*>()->_M_call
+ 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); }
@@ -909,12 +796,19 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
template<typename _Tp, typename _Req = _Require<is_base_of<_Class, _Tp>>>
auto
operator()(reference_wrapper<_Tp> __ref) const
- noexcept(noexcept(std::declval<_Mem_fn&>()(__ref.get())))
+ noexcept(noexcept(std::declval<_Mem_fn_base&>()(__ref.get())))
-> decltype((*this)(__ref.get()))
{ return (*this)(__ref.get()); }
private:
- _Res _Class::*__pm;
+ _Res _Class::*_M_pm;
+ };
+
+ template<typename _Res, typename _Class>
+ struct _Mem_fn<_Res _Class::*>
+ : _Mem_fn_base<_Res _Class::*>
+ {
+ using _Mem_fn_base<_Res _Class::*>::_Mem_fn_base;
};
// _GLIBCXX_RESOLVE_LIB_DEFECTS
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/refqual.cc b/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/refqual.cc
new file mode 100644
index 0000000..35a66e5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_objects/mem_fn/refqual.cc
@@ -0,0 +1,34 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <functional>
+
+struct Foo
+{
+ void r()&& { }
+ int l() const& { return 0; }
+};
+
+void test01()
+{
+ Foo f;
+ int i = std::mem_fn(&Foo::l)( f );
+ std::mem_fn(&Foo::r)( std::move(f) );
+}
[-- Attachment #3: patch2.txt --]
[-- Type: text/plain, Size: 4499 bytes --]
commit 9e8b41f93b5d3e6f9578fbfe9bccd7ae691733ea
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Sun Nov 2 18:35:49 2014 +0000
Check number of arguments in bind expressions.
* include/std/functional (_Mem_fn_traits_base::__arity): New typedef.
(_Mem_fn_base::_Arity): New typedef.
(_Bind_check_arity): New class template.
(_Bind_helper, _Bindres_helper, _Bind_simple_helper): Check arity.
* testsuite/20_util/bind/ref_neg.cc: Adjust dg-error.
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index ecc5bc9..f615ae4 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -515,6 +515,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
using __arg_types = _Pack<_ArgTypes...>;
using __maybe_type
= _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>;
+ using __arity = integral_constant<size_t, sizeof...(_ArgTypes)>;
};
template<typename _Res, typename _Class, typename... _ArgTypes>
@@ -634,6 +635,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
public:
using result_type = typename _Traits::__result_type;
+ using _Arity = typename _Traits::__arity;
private:
using _Class = typename _Traits::__class_type;
@@ -755,6 +757,8 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
{ return (*__ptr).*_M_pm; }
public:
+ using _Arity = integral_constant<size_t, 0>;
+
explicit
_Mem_fn_base(_Res _Class::*__pm) noexcept : _M_pm(__pm) { }
@@ -1485,6 +1489,24 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
struct is_bind_expression<const volatile _Bind_result<_Result, _Signature>>
: public true_type { };
+ template<typename _Func, typename... _BoundArgs>
+ struct _Bind_check_arity { };
+
+ template<typename _Ret, typename... _Args, typename... _BoundArgs>
+ struct _Bind_check_arity<_Ret (*)(_Args...), _BoundArgs...>
+ {
+ static_assert(sizeof...(_BoundArgs) == sizeof...(_Args),
+ "Wrong number of arguments for function");
+ };
+
+ template<typename _Tp, typename _Class, typename... _BoundArgs>
+ struct _Bind_check_arity<_Tp _Class::*, _BoundArgs...>
+ {
+ using _Arity = typename _Mem_fn<_Tp _Class::*>::_Arity;
+ static_assert(sizeof...(_BoundArgs) == _Arity::value + 1,
+ "Wrong number of arguments for pointer-to-member");
+ };
+
// Trait type used to remove std::bind() from overload set via SFINAE
// when first argument has integer type, so that std::bind() will
// not be a better match than ::bind() from the BSD Sockets API.
@@ -1493,6 +1515,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
template<bool _SocketLike, typename _Func, typename... _BoundArgs>
struct _Bind_helper
+ : _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
{
typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type>
__maybe_type;
@@ -1525,6 +1548,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
template<typename _Result, typename _Func, typename... _BoundArgs>
struct _Bindres_helper
+ : _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
{
typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type>
__maybe_type;
@@ -1599,6 +1623,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
template<typename _Func, typename... _BoundArgs>
struct _Bind_simple_helper
+ : _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
{
typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type>
__maybe_type;
diff --git a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc
index 6b315c1..1063dd3 100644
--- a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc
@@ -30,10 +30,10 @@ void test01()
{
const int dummy = 0;
std::bind(&inc, _1)(0); // { dg-error "no match" }
- // { dg-error "rvalue|const" "" { target *-*-* } 1315 }
- // { dg-error "rvalue|const" "" { target *-*-* } 1329 }
- // { dg-error "rvalue|const" "" { target *-*-* } 1343 }
- // { dg-error "rvalue|const" "" { target *-*-* } 1357 }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1213 }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1227 }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1241 }
+ // { dg-error "rvalue|const" "" { target *-*-* } 1255 }
std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" }
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-11-03 2:56 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-03 2:56 [patch] libstdc++/57898 add ref-qualifier support to std::mem_fn Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).