diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-10-13 11:19:24 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-10-13 11:19:24 +0100 |
commit | cc06c7f652d7fede4844eb1cc21b65d5c8e4efcc (patch) | |
tree | e4fb0f98937daac4b0a52cdba15d6ed65d72cfe8 | |
parent | 27947670631d8a44fd8c2984da601154b614fa81 (diff) | |
download | gcc-cc06c7f652d7fede4844eb1cc21b65d5c8e4efcc.zip gcc-cc06c7f652d7fede4844eb1cc21b65d5c8e4efcc.tar.gz gcc-cc06c7f652d7fede4844eb1cc21b65d5c8e4efcc.tar.bz2 |
Fix exception-specifications for std::_Not_fn
* include/std/functional (_Not_fn): Make exception specifications
depend on whether negating the result can throw.
* testsuite/20_util/not_fn/1.cc: Move to ...
* testsuite/20_util/function_objects/not_fn/1.cc: ... here. Add tests
for types that can throw when negated and that cannot be negated.
From-SVN: r241091
-rw-r--r-- | libstdc++-v3/ChangeLog | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/std/functional | 18 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc (renamed from libstdc++-v3/testsuite/20_util/not_fn/1.cc) | 31 |
3 files changed, 51 insertions, 4 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5ee2626..ffb78ea 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,11 @@ 2016-10-13 Jonathan Wakely <jwakely@redhat.com> + * include/std/functional (_Not_fn): Make exception specifications + depend on whether negating the result can throw. + * testsuite/20_util/not_fn/1.cc: Move to ... + * testsuite/20_util/function_objects/not_fn/1.cc: ... here. Add tests + for types that can throw when negated and that cannot be negated. + * include/bits/invoke.h (__invoke): Fix exception-specification. * include/std/functional (invoke): Likewise. * testsuite/20_util/function_objects/invoke/1.cc: New test. diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 6a45314..58134b7 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -2140,6 +2140,16 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) template<typename _Fn> class _Not_fn { + template<typename _Tp> + using __is_nothrow_negatable + = __bool_constant<noexcept(!std::declval<_Tp>())>; + + template<typename _Fn2, typename... _Args> + using __noexcept_cond = __and_< + __is_nothrow_callable<_Fn2(_Args&&...)>, + __is_nothrow_negatable<result_of_t<_Fn2(_Args&&...)>> + >; + public: template<typename _Fn2> _Not_fn(_Fn2&& __fn, int) @@ -2152,21 +2162,21 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) template<typename... _Args> auto operator()(_Args&&... __args) & - noexcept(__is_nothrow_callable<_Fn&(_Args&&...)>::value) + noexcept(__noexcept_cond<_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(__is_nothrow_callable<const _Fn&(_Args&&...)>::value) + noexcept(__noexcept_cond<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) && - noexcept(__is_nothrow_callable<_Fn&&(_Args&&...)>::value) + noexcept(__noexcept_cond<_Fn&&, _Args&&...>::value) -> decltype(!std::declval<result_of_t<_Fn&&(_Args&&...)>>()) { return !std::__invoke(std::move(_M_fn), @@ -2176,7 +2186,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) template<typename... _Args> auto operator()(_Args&&... __args) const && - noexcept(__is_nothrow_callable<const _Fn&&(_Args&&...)>::value) + noexcept(__noexcept_cond<const _Fn&&, _Args&&...>::value) -> decltype(!std::declval<result_of_t<const _Fn&&(_Args&&...)>>()) { return !std::__invoke(std::move(_M_fn), diff --git a/libstdc++-v3/testsuite/20_util/not_fn/1.cc b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc index 233a6d3..246b962 100644 --- a/libstdc++-v3/testsuite/20_util/not_fn/1.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc @@ -91,6 +91,35 @@ test05() auto copy(nf); // PR libstdc++/70564 } +void +test06() +{ + struct Boolean { + Boolean operator!() noexcept(false) { return *this; } + }; + struct F { + Boolean operator()() { return {}; } + }; + F f; + auto notf = std::not_fn(f); + using NotF = decltype(notf); + static_assert( std::is_callable<NotF()>::value, "cannot negate" ); + static_assert( !noexcept(notf()), "conversion to bool affects noexcept" ); +} + +void +test07() +{ + struct NonNegatable { }; + struct F { + NonNegatable operator()() { return {}; } + }; + F f; + auto notf = std::not_fn(f); + using NotF = decltype(notf); + static_assert( !std::is_callable<NotF()>::value, "cannot negate" ); +} + int main() { @@ -99,4 +128,6 @@ main() test03(); test04(); test05(); + test06(); + test07(); } |