diff options
| author | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-11-28 01:42:25 +0000 |
|---|---|---|
| committer | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-11-28 01:42:25 +0000 |
| commit | ef723edc44deec25ab1711c73d4ae805fdb67b22 (patch) | |
| tree | 85df2595035418bf7e5213ee9c7120e2805366ba /libstdc++-v3/include/std/functional | |
| parent | 70e63130beb949cae93507b773acd8c0056e3914 (diff) | |
| download | ppe42-gcc-ef723edc44deec25ab1711c73d4ae805fdb67b22.tar.gz ppe42-gcc-ef723edc44deec25ab1711c73d4ae805fdb67b22.zip | |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193879 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/include/std/functional')
| -rw-r--r-- | libstdc++-v3/include/std/functional | 277 |
1 files changed, 201 insertions, 76 deletions
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 0d8fbd6bdae..604481b20c4 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -501,6 +501,26 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) // @} 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 * nothing, depending on the number of arguments provided. The @@ -526,19 +546,38 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) { typedef _Res (_Class::*_Functor)(_ArgTypes...); - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res _M_call(_Tp&& __object, const volatile _Class *, - _ArgTypes... __args) const + _Args&&... __args) const { return (std::forward<_Tp>(__object).*__pmf) - (std::forward<_ArgTypes>(__args)...); + (std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res - _M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const - { return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); } + _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; @@ -546,28 +585,39 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { } // Handle objects - _Res - operator()(_Class& __object, _ArgTypes... __args) const - { return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); } + 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 - _Res - operator()(_Class* __object, _ArgTypes... __args) const - { return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); } + 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> + template<typename _Tp, typename... _Args, + typename _Req = _RequireValidArgs2<_Tp, _Args...>> _Res - operator()(_Tp&& __object, _ArgTypes... __args) const + operator()(_Tp&& __object, _Args&&... __args) const { return _M_call(std::forward<_Tp>(__object), &__object, - std::forward<_ArgTypes>(__args)...); + std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args, + typename _Req = _RequireValidArgs3<_Tp, _Args...>> _Res - operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const - { return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); } + operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const + { return operator()(__ref.get(), std::forward<_Args>(__args)...); } private: _Functor __pmf; @@ -581,19 +631,33 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) { typedef _Res (_Class::*_Functor)(_ArgTypes...) const; - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res _M_call(_Tp&& __object, const volatile _Class *, - _ArgTypes... __args) const + _Args&&... __args) const { return (std::forward<_Tp>(__object).*__pmf) - (std::forward<_ArgTypes>(__args)...); + (std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res - _M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const - { return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); } + _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<_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; @@ -601,27 +665,38 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { } // Handle objects - _Res - operator()(const _Class& __object, _ArgTypes... __args) const - { return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); } + 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)...); + } // Handle pointers - _Res - operator()(const _Class* __object, _ArgTypes... __args) const - { return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); } + template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>> + _Res + operator()(const _Class* __object, _Args&&... __args) const + { return (__object->*__pmf)(std::forward<_Args>(__args)...); } // Handle smart pointers, references and pointers to derived - template<typename _Tp> - _Res operator()(_Tp&& __object, _ArgTypes... __args) const + 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<_ArgTypes>(__args)...); + std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args, + typename _Req = _RequireValidArgs3<_Tp, _Args...>> _Res - operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const - { return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); } + operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const + { return operator()(__ref.get(), std::forward<_Args>(__args)...); } private: _Functor __pmf; @@ -635,19 +710,33 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) { typedef _Res (_Class::*_Functor)(_ArgTypes...) volatile; - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res _M_call(_Tp&& __object, const volatile _Class *, - _ArgTypes... __args) const + _Args&&... __args) const { return (std::forward<_Tp>(__object).*__pmf) - (std::forward<_ArgTypes>(__args)...); + (std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res - _M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const - { return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); } + _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<_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; @@ -655,28 +744,39 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { } // Handle objects - _Res - operator()(volatile _Class& __object, _ArgTypes... __args) const - { return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); } + 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 - _Res - operator()(volatile _Class* __object, _ArgTypes... __args) const - { return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); } + 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> + template<typename _Tp, typename... _Args, + typename _Req = _RequireValidArgs2<_Tp, _Args...>> _Res - operator()(_Tp&& __object, _ArgTypes... __args) const + operator()(_Tp&& __object, _Args&&... __args) const { return _M_call(std::forward<_Tp>(__object), &__object, - std::forward<_ArgTypes>(__args)...); + std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args, + typename _Req = _RequireValidArgs3<_Tp, _Args...>> _Res - operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const - { return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); } + operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const + { return operator()(__ref.get(), std::forward<_Args>(__args)...); } private: _Functor __pmf; @@ -690,19 +790,33 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) { typedef _Res (_Class::*_Functor)(_ArgTypes...) const volatile; - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res _M_call(_Tp&& __object, const volatile _Class *, - _ArgTypes... __args) const + _Args&&... __args) const { return (std::forward<_Tp>(__object).*__pmf) - (std::forward<_ArgTypes>(__args)...); + (std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args> _Res - _M_call(_Tp&& __ptr, const volatile void *, _ArgTypes... __args) const - { return ((*__ptr).*__pmf)(std::forward<_ArgTypes>(__args)...); } + _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<_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; @@ -710,27 +824,38 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) explicit _Mem_fn(_Functor __pmf) : __pmf(__pmf) { } // Handle objects - _Res - operator()(const volatile _Class& __object, _ArgTypes... __args) const - { return (__object.*__pmf)(std::forward<_ArgTypes>(__args)...); } + 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 + { + return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...); + } // Handle pointers - _Res - operator()(const volatile _Class* __object, _ArgTypes... __args) const - { return (__object->*__pmf)(std::forward<_ArgTypes>(__args)...); } + template<typename... _Args, typename _Req = _RequireValidArgs<_Args...>> + _Res + operator()(const volatile _Class* __object, _Args&&... __args) const + { return (__object->*__pmf)(std::forward<_Args>(__args)...); } // Handle smart pointers, references and pointers to derived - template<typename _Tp> - _Res operator()(_Tp&& __object, _ArgTypes... __args) const + 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<_ArgTypes>(__args)...); + std::forward<_Args>(__args)...); } - template<typename _Tp> + template<typename _Tp, typename... _Args, + typename _Req = _RequireValidArgs3<_Tp, _Args...>> _Res - operator()(reference_wrapper<_Tp> __ref, _ArgTypes... __args) const - { return operator()(__ref.get(), std::forward<_ArgTypes>(__args)...); } + operator()(reference_wrapper<_Tp> __ref, _Args&&... __args) const + { return operator()(__ref.get(), std::forward<_Args>(__args)...); } private: _Functor __pmf; @@ -756,7 +881,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) // This bit of genius is due to Peter Dimov, improved slightly by // Douglas Gregor. - // Made less elegant by Jonathan Wakely to support perfect forwarding. + // Made less elegant to support perfect forwarding and noexcept. template<typename _Tp> auto _M_call(_Tp&& __object, const _Class *) const noexcept @@ -807,7 +932,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) { return __object->*__pm; } // Handle smart pointers and derived - template<typename _Tp> + template<typename _Tp, typename _Req = _Require<_NotSame<_Class*, _Tp>>> auto operator()(_Tp&& __unknown) const 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)) { return _M_call(std::forward<_Tp>(__unknown), &__unknown); } - template<typename _Tp> + 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()))) -> decltype((*this)(__ref.get())) - { return operator()(__ref.get()); } + { return (*this)(__ref.get()); } private: _Res _Class::*__pm; |

