From eb8bf686b7877f9000aefd599b4ad035475b7e99 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 3 Sep 2015 15:36:03 +0100 Subject: [PATCH] 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 --- libstdc++-v3/ChangeLog | 7 ++++ libstdc++-v3/include/experimental/functional | 32 +++++++++++++------ .../experimental/functional/not_fn.cc | 32 +++++++++++++++++-- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 099863ddafc..eb4758901ec 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2015-09-03 Jonathan Wakely + 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 c6b9800f7a6..9db5fefcbcc 100644 --- a/libstdc++-v3/include/experimental/functional +++ b/libstdc++-v3/include/experimental/functional @@ -376,8 +376,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Generalized negator. template - struct _Not_fn + class _Not_fn { + _Fn _M_fn; + + public: template explicit _Not_fn(_Fn2&& __fn) : _M_fn(std::forward<_Fn2>(__fn)) { } @@ -389,34 +392,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ~_Not_fn() = default; template - 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 - 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 - 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 - 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 + template inline auto not_fn(_Fn&& __fn) - { return _Not_fn>{std::forward<_Fn>(__fn)}; } + noexcept(std::is_nothrow_constructible, _Fn&&>::value) + { + using __maybe_type = _Maybe_wrap_member_pointer>; + return _Not_fn{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 #include +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 +auto foo(F f, Arg arg) -> decltype(not_fn(f)(arg)) { return not_fn(f)(arg); } + +template +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(); } -- 2.30.2