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:
parent
500dc9a6c3
commit
eb8bf686b7
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user