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
This commit is contained in:
Jonathan Wakely 2015-09-03 15:36:03 +01:00 committed by Jonathan Wakely
parent 500dc9a6c3
commit eb8bf686b7
3 changed files with 59 additions and 12 deletions

View File

@ -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.

View File

@ -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

View File

@ -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();
}