diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2015-09-03 15:36:03 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2015-09-03 15:36:03 +0100 |
commit | eb8bf686b7877f9000aefd599b4ad035475b7e99 (patch) | |
tree | 8329be86b1fdc2543a47bfd3f061bebbd1f8dacb /libstdc++-v3 | |
parent | 500dc9a6c335fba9be0c2aa9c6c489b7e09c8400 (diff) | |
download | gcc-eb8bf686b7877f9000aefd599b4ad035475b7e99.zip gcc-eb8bf686b7877f9000aefd599b4ad035475b7e99.tar.gz gcc-eb8bf686b7877f9000aefd599b4ad035475b7e99.tar.bz2 |
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.
From-SVN: r227448
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 099863d..eb47589 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. + PR libstdc++/62039 * include/bits/stl_iterator_base_funcs.h (next, prev): Add concept checks. diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional index c6b9800..9db5fef 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 8285ec4..4c137e8 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(); } |