diff options
author | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-09-03 15:10:52 +0000 |
---|---|---|
committer | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-09-03 15:10:52 +0000 |
commit | 2cdea5a23c4733fe92ed4ce1838a272748baa004 (patch) | |
tree | f50be5af8f3db80eb2671f8aa7d275e7f000d64e /libstdc++-v3 | |
parent | 7cf39944ff56a294488d1e14a4f27591223ab642 (diff) | |
download | gcc-2cdea5a23c4733fe92ed4ce1838a272748baa004.tar.gz |
Make std::experimental::not_fn SFINAE-friendly.
PR libstdc++/66998
* include/experimental/functional (_Not_fn): Add exception
specifications and non-deduced return types.
(not_fn): Add exception specification and wrap pointer-to-member.
* testsuite/experimental/functional/not_fn.cc: Test in SFINAE context
and test pointer-to-member.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-5-branch@227455 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/functional | 32 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/functional/not_fn.cc | 32 |
3 files changed, 59 insertions, 12 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 41e21b08ea4..07fbb3151c9 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2015-09-03 Jonathan Wakely <jwakely@redhat.com> + PR libstdc++/66998 + * include/experimental/functional (_Not_fn): Add exception + specifications and non-deduced return types. + (not_fn): Add exception specification and wrap pointer-to-member. + * testsuite/experimental/functional/not_fn.cc: Test in SFINAE context + and test pointer-to-member. + Backport from mainline 2015-08-27 Jonathan Wakely <jwakely@redhat.com> diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional index 0472f593df5..40d3bd44d1e 100644 --- a/libstdc++-v3/include/experimental/functional +++ b/libstdc++-v3/include/experimental/functional @@ -376,8 +376,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Generalized negator. template<typename _Fn> - struct _Not_fn + class _Not_fn { + _Fn _M_fn; + + public: template<typename _Fn2> explicit _Not_fn(_Fn2&& __fn) : _M_fn(std::forward<_Fn2>(__fn)) { } @@ -389,34 +392,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ~_Not_fn() = default; template<typename... _Args> - decltype(auto) + auto operator()(_Args&&... __args) + noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...))) + -> decltype(!_M_fn(std::forward<_Args>(__args)...)) { return !_M_fn(std::forward<_Args>(__args)...); } template<typename... _Args> - decltype(auto) + auto operator()(_Args&&... __args) const + noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...))) + -> decltype(!_M_fn(std::forward<_Args>(__args)...)) { return !_M_fn(std::forward<_Args>(__args)...); } template<typename... _Args> - decltype(auto) + auto operator()(_Args&&... __args) volatile + noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...))) + -> decltype(!_M_fn(std::forward<_Args>(__args)...)) { return !_M_fn(std::forward<_Args>(__args)...); } template<typename... _Args> - decltype(auto) + auto operator()(_Args&&... __args) const volatile + noexcept(noexcept(!_M_fn(std::forward<_Args>(__args)...))) + -> decltype(!_M_fn(std::forward<_Args>(__args)...)) { return !_M_fn(std::forward<_Args>(__args)...); } - - private: - _Fn _M_fn; }; /// [func.not_fn] Function template not_fn - template <class _Fn> + template<typename _Fn> inline auto not_fn(_Fn&& __fn) - { return _Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn)}; } + noexcept(std::is_nothrow_constructible<std::decay_t<_Fn>, _Fn&&>::value) + { + using __maybe_type = _Maybe_wrap_member_pointer<std::decay_t<_Fn>>; + return _Not_fn<typename __maybe_type::type>{std::forward<_Fn>(__fn)}; + } _GLIBCXX_END_NAMESPACE_VERSION } // namespace fundamentals_v2 diff --git a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc index 8285ec4fbf5..4c137e85bea 100644 --- a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc +++ b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc @@ -20,6 +20,8 @@ #include <experimental/functional> #include <testsuite_hooks.h> +using std::experimental::not_fn; + int func(int, char) { return 0; } struct F @@ -33,8 +35,6 @@ struct F void test01() { - using std::experimental::not_fn; - auto f1 = not_fn(func); VERIFY( f1(1, '2') == true ); @@ -50,8 +50,36 @@ test01() VERIFY( f5(1) == false ); } +template<typename F, typename Arg> +auto foo(F f, Arg arg) -> decltype(not_fn(f)(arg)) { return not_fn(f)(arg); } + +template<typename F, typename Arg> +auto foo(F f, Arg arg) -> decltype(not_fn(f)()) { return not_fn(f)(); } + +struct negator +{ + bool operator()(int) const { return false; } + void operator()() const {} +}; + +void +test02() +{ + foo(negator{}, 1); // PR libstdc++/66998 +} + +void +test03() +{ + struct X { bool b; }; + X x{ false }; + VERIFY( not_fn(&X::b)(x) ); +} + int main() { test01(); + test02(); + test03(); } |