* [PATCH] PR 70564 disambiguate constructors for not_fn call wrapper
@ 2016-10-05 11:31 Jonathan Wakely
2016-10-05 12:40 ` Jonathan Wakely
2016-10-05 12:43 ` Jonathan Wakely
0 siblings, 2 replies; 3+ messages in thread
From: Jonathan Wakely @ 2016-10-05 11:31 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 981 bytes --]
The _Not_fn::_Not_fn<_Fn2>(_Fn2&&) ctor gets chosen by overload
resolution when trying to copy the call wrapper object (although only
for direct-initialization, because it's explicit). Rather than
constraining it using SFINAE I'm just adding a second parameter, so it
isn't viable for copying or moving the call wrapper.
I'm also reusing std::_Not_fn for std::experimental::not_fn, so we
don't need to fix bugs like this twice. _Not_fn uses std::invoke and
std::is_nothrow_callable, but we have __nonstandard versions of both
available in C++14.
PR libstdc++/70564
* include/experimental/functional (_Not_fn): Remove.
(not_fn): Use std::_Not_fn.
* include/std/functional (_Not_fn): Add second parameter to
disambiguate copying from initialization by not_fn. Define for C++14.
(not_fn): Add second argument to initialization.
* testsuite/20_util/not_fn/1.cc: Copy call wrapper using
direct-initialization.
Tested powerpc64le-linux, committing to trunk and gcc-6-branch.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 6824 bytes --]
commit a8f00b884083e0ffd9e9aaa919f6ea95adc57c2e
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Wed Oct 5 11:22:36 2016 +0100
PR 70564 disambiguate constructors for not_fn call wrapper
PR libstdc++/70564
* include/experimental/functional (_Not_fn): Remove.
(not_fn): Use std::_Not_fn.
* include/std/functional (_Not_fn): Add second parameter to
disambiguate copying from initialization by not_fn. Define for C++14.
(not_fn): Add second argument to initialization.
* testsuite/20_util/not_fn/1.cc: Copy call wrapper using
direct-initialization.
diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 082e58c..db45665 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -378,64 +378,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define __cpp_lib_experimental_not_fn 201406
- /// Generalized negator.
- template<typename _Fn>
- class _Not_fn
- {
- _Fn _M_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<_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)
- -> 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)
- -> 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<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
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)};
+ return std::_Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn), 0};
}
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 74e65c7..1c7523e 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -2139,19 +2139,14 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
{ __x.swap(__y); }
-
-#if __cplusplus > 201402L
-
-#define __cpp_lib_not_fn 201603
-
- /// Generalized negator.
+#if __cplusplus >= 201402L
+ /// Generalized negator.
template<typename _Fn>
class _Not_fn
{
public:
template<typename _Fn2>
- explicit
- _Not_fn(_Fn2&& __fn)
+ _Not_fn(_Fn2&& __fn, int)
: _M_fn(std::forward<_Fn2>(__fn)) { }
_Not_fn(const _Not_fn& __fn) = default;
@@ -2161,21 +2156,21 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
template<typename... _Args>
auto
operator()(_Args&&... __args) &
- noexcept(is_nothrow_callable_v<_Fn&(_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(is_nothrow_callable_v<const _Fn&(_Args&&...)>)
+ 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) &&
- noexcept(is_nothrow_callable_v<_Fn&&(_Args&&...)>)
+ noexcept(__is_nothrow_callable<_Fn&&(_Args&&...)>::value)
-> decltype(!std::declval<result_of_t<_Fn&&(_Args&&...)>>())
{
return !std::__invoke(std::move(_M_fn),
@@ -2185,7 +2180,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
template<typename... _Args>
auto
operator()(_Args&&... __args) const &&
- noexcept(is_nothrow_callable_v<const _Fn&&(_Args&&...)>)
+ noexcept(__is_nothrow_callable<const _Fn&&(_Args&&...)>::value)
-> decltype(!std::declval<result_of_t<const _Fn&&(_Args&&...)>>())
{
return !std::__invoke(std::move(_M_fn),
@@ -2195,6 +2190,11 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
private:
_Fn _M_fn;
};
+#endif // C++14
+
+#if __cplusplus > 201402L
+
+#define __cpp_lib_not_fn 201603
/// [func.not_fn] Function template not_fn
template<typename _Fn>
@@ -2202,7 +2202,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
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)};
+ return _Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn), 0};
}
// Searchers
@@ -2515,7 +2515,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
return std::make_pair(__last, __last);
}
-#endif
+#endif // C++17
_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
index 375c7cc..8d6e9ec 100644
--- a/libstdc++-v3/testsuite/20_util/not_fn/1.cc
+++ b/libstdc++-v3/testsuite/20_util/not_fn/1.cc
@@ -84,6 +84,12 @@ test04()
VERIFY( not_fn(f)(d) );
}
+void
+test05()
+{
+ auto nf{ std::not_fn([] { return false; }) };
+}
+
int
main()
{
@@ -91,4 +97,5 @@ main()
test02();
test03();
test04();
+ test05();
}
diff --git a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
index d508028..59d7621 100644
--- a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
+++ b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
@@ -84,6 +84,12 @@ test04()
VERIFY( not_fn(f)(d) );
}
+void
+test05()
+{
+ auto nf{ not_fn([] { return false; }) };
+}
+
int
main()
{
@@ -91,4 +97,5 @@ main()
test02();
test03();
test04();
+ test05();
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] PR 70564 disambiguate constructors for not_fn call wrapper
2016-10-05 11:31 [PATCH] PR 70564 disambiguate constructors for not_fn call wrapper Jonathan Wakely
@ 2016-10-05 12:40 ` Jonathan Wakely
2016-10-05 12:43 ` Jonathan Wakely
1 sibling, 0 replies; 3+ messages in thread
From: Jonathan Wakely @ 2016-10-05 12:40 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1010 bytes --]
On 05/10/16 12:31 +0100, Jonathan Wakely wrote:
>diff --git a/libstdc++-v3/testsuite/20_util/not_fn/1.cc b/libstdc++-v3/testsuite/20_util/not_fn/1.cc
>index 375c7cc..8d6e9ec 100644
>--- a/libstdc++-v3/testsuite/20_util/not_fn/1.cc
>+++ b/libstdc++-v3/testsuite/20_util/not_fn/1.cc
>@@ -84,6 +84,12 @@ test04()
> VERIFY( not_fn(f)(d) );
> }
>
>+void
>+test05()
>+{
>+ auto nf{ std::not_fn([] { return false; }) };
>+}
>+
> int
> main()
> {
>diff --git a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
>index d508028..59d7621 100644
>--- a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
>+++ b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
>@@ -84,6 +84,12 @@ test04()
> VERIFY( not_fn(f)(d) );
> }
>
>+void
>+test05()
>+{
>+ auto nf{ not_fn([] { return false; }) };
>+}
>+
> int
> main()
> {
Gah, this aren't the tests I meant to commit. Fixed on trunk like so,
with tests that actually failed before the fix.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 1224 bytes --]
commit 998cf48ef12d44d215acb70f80600e46648da94f
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Wed Oct 5 13:19:38 2016 +0100
70564 fix newly-added tests for not_fn
PR libstdc++/70564
* testsuite/20_util/not_fn/1.cc: Fix test.
* testsuite/experimental/functional/not_fn.cc: Likewise.
diff --git a/libstdc++-v3/testsuite/20_util/not_fn/1.cc b/libstdc++-v3/testsuite/20_util/not_fn/1.cc
index 8d6e9ec..233a6d3 100644
--- a/libstdc++-v3/testsuite/20_util/not_fn/1.cc
+++ b/libstdc++-v3/testsuite/20_util/not_fn/1.cc
@@ -87,7 +87,8 @@ test04()
void
test05()
{
- auto nf{ std::not_fn([] { return false; }) };
+ auto nf = std::not_fn([] { return false; });
+ auto copy(nf); // PR libstdc++/70564
}
int
diff --git a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
index 59d7621..525f59c 100644
--- a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
+++ b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
@@ -87,7 +87,8 @@ test04()
void
test05()
{
- auto nf{ not_fn([] { return false; }) };
+ auto nf = std::experimental::not_fn([] { return false; });
+ auto copy(nf); // PR libstdc++/70564
}
int
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] PR 70564 disambiguate constructors for not_fn call wrapper
2016-10-05 11:31 [PATCH] PR 70564 disambiguate constructors for not_fn call wrapper Jonathan Wakely
2016-10-05 12:40 ` Jonathan Wakely
@ 2016-10-05 12:43 ` Jonathan Wakely
1 sibling, 0 replies; 3+ messages in thread
From: Jonathan Wakely @ 2016-10-05 12:43 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 239 bytes --]
On 05/10/16 12:31 +0100, Jonathan Wakely wrote:
>Tested powerpc64le-linux, committing to trunk and gcc-6-branch.
And here's the slightly diffeernt patch for the branch (because we
only have experimental::not_fn there, not std::not_fn).
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 2308 bytes --]
commit 2484aeb5b25372c3a7833a000b798e3bf6f41c6b
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Wed Oct 5 12:01:36 2016 +0000
PR 70564 disambiguate constructor for not_fn call wrapper
PR libstdc++/70564
* include/experimental/functional (_Not_fn): Add second parameter to
disambiguate copying from initialization by not_fn.
(not_fn): Add second argument to initialization.
* testsuite/experimental/functional/not_fn.cc: Copy call wrapper using
direct-initialization. Test abstract class.
diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 0b91dcd..6a21caf 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -387,7 +387,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
template<typename _Fn2>
explicit
- _Not_fn(_Fn2&& __fn) : _M_fn(std::forward<_Fn2>(__fn)) { }
+ _Not_fn(_Fn2&& __fn, int) : _M_fn(std::forward<_Fn2>(__fn)) { }
_Not_fn(const _Not_fn& __fn) = default;
_Not_fn(_Not_fn&& __fn) = default;
@@ -431,7 +431,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
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<typename __maybe_type::type>{std::forward<_Fn>(__fn), 0};
}
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
index 3096eaa..b69d3ac 100644
--- a/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
+++ b/libstdc++-v3/testsuite/experimental/functional/not_fn.cc
@@ -76,10 +76,30 @@ 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) );
+}
+
+void
+test05()
+{
+ auto nf = std::experimental::not_fn([] { return false; });
+ auto copy(nf); // PR libstdc++/70564
+}
+
int
main()
{
test01();
test02();
test03();
+ test04();
+ test05();
}
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-10-05 12:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-05 11:31 [PATCH] PR 70564 disambiguate constructors for not_fn call wrapper Jonathan Wakely
2016-10-05 12:40 ` Jonathan Wakely
2016-10-05 12:43 ` Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).