diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-08-19 16:42:34 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-08-19 16:42:34 +0100 |
commit | e6ee5bfd688c09abebddbe39beb3422163dfafd8 (patch) | |
tree | 245e6dcb2993e4fe3da21092b3434f65462ec2b6 /libstdc++-v3 | |
parent | 387edf83a033e1a534c7a2a076d5ae691ecbac07 (diff) | |
download | gcc-e6ee5bfd688c09abebddbe39beb3422163dfafd8.tar.gz |
Define std::not_fn for C++17
* doc/xml/manual/status_cxx2017.xml: Update status of not_fn.
* doc/html/*: Regenerate.
* include/experimental/functional (_Not_fn, not_fn): Match C++17
semantics.
* include/std/functional (_Not_fn, not_fn): Define for C++17.
* testsuite/20_util/not_fn/1.cc: New.
* testsuite/experimental/functional/not_fn.cc: Test abstract class.
Remove test for volatile-qualified wrapper.
From-SVN: r239623
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 9 | ||||
-rw-r--r-- | libstdc++-v3/doc/html/manual/status.html | 4 | ||||
-rw-r--r-- | libstdc++-v3/doc/xml/manual/status_cxx2017.xml | 3 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/functional | 46 | ||||
-rw-r--r-- | libstdc++-v3/include/std/functional | 68 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/not_fn/1.cc | 94 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/functional/not_fn.cc | 15 |
7 files changed, 211 insertions, 28 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 727285a8043..5239600749c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,14 @@ 2016-08-19 Jonathan Wakely <jwakely@redhat.com> + * doc/xml/manual/status_cxx2017.xml: Update status of not_fn. + * doc/html/*: Regenerate. + * include/experimental/functional (_Not_fn, not_fn): Match C++17 + semantics. + * include/std/functional (_Not_fn, not_fn): Define for C++17. + * testsuite/20_util/not_fn/1.cc: New. + * testsuite/experimental/functional/not_fn.cc: Test abstract class. + Remove test for volatile-qualified wrapper. + * include/std/atomic (atomic::is_always_lock_free): Define. * testsuite/29_atomics/atomic/60695.cc: Adjust dg-error lineno. * testsuite/29_atomics/atomic/is_always_lock_free.cc: New. diff --git a/libstdc++-v3/doc/html/manual/status.html b/libstdc++-v3/doc/html/manual/status.html index 64606393711..e82739aa1ce 100644 --- a/libstdc++-v3/doc/html/manual/status.html +++ b/libstdc++-v3/doc/html/manual/status.html @@ -578,11 +578,11 @@ Feature-testing recommendations for C++</a>. <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4277.html" target="_top"> N4277 </a> - </td><td align="center"> 5.1 </td><td align="left"> </td></tr><tr bgcolor="#C8B0B0"><td align="left"> Adopt <code class="code">not_fn</code> from Library Fundamentals 2 for C++17 </td><td align="left"> + </td><td align="center"> 5.1 </td><td align="left"> </td></tr><tr><td align="left"> Adopt <code class="code">not_fn</code> from Library Fundamentals 2 for C++17 </td><td align="left"> <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0005r4.html" target="_top"> P0005R4 </a> - </td><td align="center"> No </td><td align="left"><code class="code">__cpp_lib_not_fn >= 201603</code></td></tr><tr bgcolor="#C8B0B0"><td align="left"> Fixes for <code class="code">not_fn</code> </td><td align="left"> + </td><td align="center"> 7 </td><td align="left"><code class="code">__cpp_lib_not_fn >= 201603</code></td></tr><tr bgcolor="#C8B0B0"><td align="left"> Fixes for <code class="code">not_fn</code> </td><td align="left"> <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0358r1.html" target="_top"> P0358R1 </a> diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml index 331420ef3ce..ff966272311 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml @@ -321,14 +321,13 @@ Feature-testing recommendations for C++</link>. </row> <row> - <?dbhtml bgcolor="#C8B0B0" ?> <entry> Adopt <code>not_fn</code> from Library Fundamentals 2 for C++17 </entry> <entry> <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0005r4.html"> P0005R4 </link> </entry> - <entry align="center"> No </entry> + <entry align="center"> 7 </entry> <entry><code>__cpp_lib_not_fn >= 201603</code></entry> </row> diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional index ed41f5a3982..eddbcf11c9c 100644 --- a/libstdc++-v3/include/experimental/functional +++ b/libstdc++-v3/include/experimental/functional @@ -386,41 +386,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: template<typename _Fn2> explicit - _Not_fn(_Fn2&& __fn) : _M_fn(std::forward<_Fn2>(__fn)) { } + _Not_fn(_Fn2&& __fn) + : _M_fn(std::forward<_Fn2>(__fn)) { } _Not_fn(const _Not_fn& __fn) = default; _Not_fn(_Not_fn&& __fn) = default; - _Not_fn& operator=(const _Not_fn& __fn) = default; - _Not_fn& operator=(_Not_fn&& __fn) = default; ~_Not_fn() = default; template<typename... _Args> 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)...); } + operator()(_Args&&... __args) & + noexcept(__is_nothrow_callable<_Fn&(_Args&&...)>::value) + -> decltype(!std::declval<result_of_t<_Fn&(_Args&&...)>>()) + { return !std::__invoke(_M_fn, std::forward<_Args>(__args)...); } template<typename... _Args> 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)...); } + operator()(_Args&&... __args) const & + noexcept(__is_nothrow_callable<const _Fn&(_Args&&...)>::value) + -> decltype(!std::declval<result_of_t<const _Fn&(_Args&&...)>>()) + { return !std::__invoke(_M_fn, std::forward<_Args>(__args)...); } template<typename... _Args> 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)...); } + operator()(_Args&&... __args) && + noexcept(__is_nothrow_callable<_Fn&&(_Args&&...)>::value) + -> decltype(!std::declval<result_of_t<_Fn&&(_Args&&...)>>()) + { + return !std::__invoke(std::move(_M_fn), + std::forward<_Args>(__args)...); + } template<typename... _Args> 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)...); } + operator()(_Args&&... __args) const && + noexcept(__is_nothrow_callable<const _Fn&&(_Args&&...)>::value) + -> decltype(!std::declval<result_of_t<const _Fn&&(_Args&&...)>>()) + { + return !std::__invoke(std::move(_M_fn), + std::forward<_Args>(__args)...); + } }; /// [func.not_fn] Function template not_fn @@ -429,8 +434,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION not_fn(_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)}; + return _Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn)}; } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 86081346cf6..87d1c17d166 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -2129,6 +2129,74 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) { __x.swap(__y); } + +#if __cplusplus > 201402L + +#define __cpp_lib_not_fn 201603 + + /// Generalized negator. + template<typename _Fn> + class _Not_fn + { + public: + template<typename _Fn2> + explicit + _Not_fn(_Fn2&& __fn) + : _M_fn(std::forward<_Fn2>(__fn)) { } + + _Not_fn(const _Not_fn& __fn) = default; + _Not_fn(_Not_fn&& __fn) = default; + ~_Not_fn() = default; + + template<typename... _Args> + auto + operator()(_Args&&... __args) & + noexcept(is_nothrow_callable_v<_Fn&(_Args&&...)>) + -> decltype(!std::declval<result_of_t<_Fn&(_Args&&...)>>()) + { return !std::__invoke(_M_fn, std::forward<_Args>(__args)...); } + + template<typename... _Args> + auto + operator()(_Args&&... __args) const & + noexcept(is_nothrow_callable_v<const _Fn&(_Args&&...)>) + -> decltype(!std::declval<result_of_t<const _Fn&(_Args&&...)>>()) + { return !std::__invoke(_M_fn, std::forward<_Args>(__args)...); } + + template<typename... _Args> + auto + operator()(_Args&&... __args) && + noexcept(is_nothrow_callable_v<_Fn&&(_Args&&...)>) + -> decltype(!std::declval<result_of_t<_Fn&&(_Args&&...)>>()) + { + return !std::__invoke(std::move(_M_fn), + std::forward<_Args>(__args)...); + } + + template<typename... _Args> + auto + operator()(_Args&&... __args) const && + noexcept(is_nothrow_callable_v<const _Fn&&(_Args&&...)>) + -> decltype(!std::declval<result_of_t<const _Fn&&(_Args&&...)>>()) + { + return !std::__invoke(std::move(_M_fn), + std::forward<_Args>(__args)...); + } + + private: + _Fn _M_fn; + }; + + /// [func.not_fn] Function template not_fn + template<typename _Fn> + inline auto + not_fn(_Fn&& __fn) + noexcept(std::is_nothrow_constructible<std::decay_t<_Fn>, _Fn&&>::value) + { + return _Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn)}; + } + +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/testsuite/20_util/not_fn/1.cc b/libstdc++-v3/testsuite/20_util/not_fn/1.cc new file mode 100644 index 00000000000..375c7cc1367 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/not_fn/1.cc @@ -0,0 +1,94 @@ +// Copyright (C) 2014-2016 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++17" } + +#include <functional> +#include <testsuite_hooks.h> + +using std::not_fn; + +int func(int, char) { return 0; } + +struct F +{ + bool operator()() { return false; } + bool operator()() const { return true; } + bool operator()(int) { return false; } +}; + +void +test01() +{ + auto f1 = not_fn(func); + VERIFY( f1(1, '2') == true ); + + auto f2 = not_fn( [] { return true; } ); + VERIFY( f2() == false ); + + auto f3 = not_fn( F{} ); + VERIFY( f3() == true ); + VERIFY( f3(1) == true ); + const auto f4 = f3; + VERIFY( f4() == 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) ); +} + +void +test04() +{ + struct abstract { virtual void f() = 0; }; + struct derived : abstract { void f() { } }; + struct F { bool operator()(abstract&) { return false; } }; + F f; + derived d; + VERIFY( not_fn(f)(d) ); +} + +int +main() +{ + test01(); + test02(); + test03(); + test04(); +} diff --git a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc index 3096eaae79e..1b3adf10899 100644 --- a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc +++ b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc @@ -29,7 +29,6 @@ struct F bool operator()() { return false; } bool operator()() const { return true; } bool operator()(int) { return false; } - bool operator()(int) volatile { return true; } }; void @@ -46,8 +45,6 @@ test01() VERIFY( f3(1) == true ); const auto f4 = f3; VERIFY( f4() == false ); - volatile auto f5 = f3; - VERIFY( f5(1) == false ); } template<typename F, typename Arg> @@ -76,10 +73,22 @@ test03() VERIFY( not_fn(&X::b)(x) ); } +void +test04() +{ + struct abstract { virtual void f() = 0; }; + struct derived : abstract { void f() { } }; + struct F { bool operator()(abstract&) { return false; } }; + F f; + derived d; + VERIFY( not_fn(f)(d) ); +} + int main() { test01(); test02(); test03(); + test04(); } |