diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2017-03-10 15:29:38 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2017-03-10 15:29:38 +0000 |
commit | 7dcc645ccd085045f628a25760788221cb83c504 (patch) | |
tree | 4ad614b7e968ead7b07abb7d482f04d23bc2ee2c | |
parent | a147ef113d5c6c0fd44e2de7149c8fbd1e2a7882 (diff) | |
download | gcc-7dcc645ccd085045f628a25760788221cb83c504.zip gcc-7dcc645ccd085045f628a25760788221cb83c504.tar.gz gcc-7dcc645ccd085045f628a25760788221cb83c504.tar.bz2 |
P0604R0 add invoke_result, is_invocable etc. for C++17
* include/bits/invoke.h (__invoke): Use __invoke_result instead of
result_of, and __is_nothrow_invocable instead of
__is_nothrow_callable.
* include/bits/shared_ptr_base.h (__shared_ptr): Use __is_invocable
instead of __is_callable.
* include/std/functional (invoke): use invoke_result_t instead of
result_of_t and is_nothrow_invocable instead of is_nothrow_callable.
(_Not_fn): Use __invoke_result instead of result_of.
* include/std/type_traits (__result_of_memobj, __result_of_memfun):
Remove partial specializations for reference_wrapper types.
(__result_of_impl): Use __inv_unwrap to strip reference_wrapper.
(__invoke_result): Define replacement for result_of and then use it to
define result_of.
(__is_callable_impl, __is_callable, __is_nothrow_callable): Replace
with __is_invocable_impl, __is_invocable, and __is_nothrow_invocable
respectively.
(invoke_result, invoke_result_t): Define for C++17.
(is_callable, is_nothrow_callable): Replace with is_invocable,
is_invocable_r, is_nothrow_invocable, and is_nothrow_invocable_r.
(is_callable_v, is_nothrow_callable_v): Replace with is_invocable_v,
is_invocable_r_v, is_nothrow_invocable_v, and is_nothrow_invocable_r_v.
* include/std/variant (hash<variant<T...>>): Use is_nothrow_invocable_v
instead of is_nothrow_callable_v.
* testsuite/20_util/function_objects/invoke/59768.cc: Remove unused
main function.
* testsuite/20_util/function_objects/not_fn/1.cc: Use is_invocable
instead of is_callable.
* testsuite/20_util/is_callable/*: Rename directory and adjust tests
to use new traits.
* testsuite/20_util/is_notjrow_callable/*: Likewise.
* testsuite/20_util/optional/hash.cc: Use is_invocable_v instead of
is_callable.
* testsuite/20_util/variant/hash.cc: Likewise.
From-SVN: r246036
24 files changed, 511 insertions, 444 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d94f6d4..a6ae03d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,39 @@ +2017-03-10 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/invoke.h (__invoke): Use __invoke_result instead of + result_of, and __is_nothrow_invocable instead of + __is_nothrow_callable. + * include/bits/shared_ptr_base.h (__shared_ptr): Use __is_invocable + instead of __is_callable. + * include/std/functional (invoke): use invoke_result_t instead of + result_of_t and is_nothrow_invocable instead of is_nothrow_callable. + (_Not_fn): Use __invoke_result instead of result_of. + * include/std/type_traits (__result_of_memobj, __result_of_memfun): + Remove partial specializations for reference_wrapper types. + (__result_of_impl): Use __inv_unwrap to strip reference_wrapper. + (__invoke_result): Define replacement for result_of and then use it to + define result_of. + (__is_callable_impl, __is_callable, __is_nothrow_callable): Replace + with __is_invocable_impl, __is_invocable, and __is_nothrow_invocable + respectively. + (invoke_result, invoke_result_t): Define for C++17. + (is_callable, is_nothrow_callable): Replace with is_invocable, + is_invocable_r, is_nothrow_invocable, and is_nothrow_invocable_r. + (is_callable_v, is_nothrow_callable_v): Replace with is_invocable_v, + is_invocable_r_v, is_nothrow_invocable_v, and is_nothrow_invocable_r_v. + * include/std/variant (hash<variant<T...>>): Use is_nothrow_invocable_v + instead of is_nothrow_callable_v. + * testsuite/20_util/function_objects/invoke/59768.cc: Remove unused + main function. + * testsuite/20_util/function_objects/not_fn/1.cc: Use is_invocable + instead of is_callable. + * testsuite/20_util/is_callable/*: Rename directory and adjust tests + to use new traits. + * testsuite/20_util/is_notjrow_callable/*: Likewise. + * testsuite/20_util/optional/hash.cc: Use is_invocable_v instead of + is_callable. + * testsuite/20_util/variant/hash.cc: Likewise. + 2017-03-10 George Lander <george.lander@arm.com> * acinclude.m4 (glibcxx_cv_obsolete_isnan): Define diff --git a/libstdc++-v3/include/bits/invoke.h b/libstdc++-v3/include/bits/invoke.h index 56d9afb..eba8707 100644 --- a/libstdc++-v3/include/bits/invoke.h +++ b/libstdc++-v3/include/bits/invoke.h @@ -85,13 +85,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Invoke a callable object. template<typename _Callable, typename... _Args> - constexpr typename result_of<_Callable&&(_Args&&...)>::type + constexpr typename __invoke_result<_Callable, _Args...>::type __invoke(_Callable&& __fn, _Args&&... __args) - noexcept(__is_nothrow_callable<_Callable&&(_Args&&...)>::value) + noexcept(__is_nothrow_invocable<_Callable, _Args...>::value) { - using __result_of = result_of<_Callable&&(_Args&&...)>; - using __type = typename __result_of::type; - using __tag = typename __result_of::__invoke_type; + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), std::forward<_Args>(__args)...); } diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index 770a094..a203f42 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -1085,7 +1085,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __shared_ptr(_Yp* __p, _Deleter __d) : _M_ptr(__p), _M_refcount(__p, __d) { - static_assert(__is_callable<_Deleter&(_Yp*&)>::value, + static_assert(__is_invocable<_Deleter&, _Yp*&>::value, "deleter expression d(p) is well-formed"); _M_enable_shared_from_this_with(__p); } @@ -1095,7 +1095,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a) : _M_ptr(__p), _M_refcount(__p, __d, std::move(__a)) { - static_assert(__is_callable<_Deleter&(_Yp*&)>::value, + static_assert(__is_invocable<_Deleter&, _Yp*&>::value, "deleter expression d(p) is well-formed"); _M_enable_shared_from_this_with(__p); } diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 366a7fb..ae5bc0a 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -73,9 +73,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Invoke a callable object. template<typename _Callable, typename... _Args> - inline result_of_t<_Callable&&(_Args&&...)> + inline invoke_result_t<_Callable, _Args...> invoke(_Callable&& __fn, _Args&&... __args) - noexcept(is_nothrow_callable_v<_Callable&&(_Args&&...)>) + noexcept(is_nothrow_invocable_v<_Callable, _Args...>) { return std::__invoke(std::forward<_Callable>(__fn), std::forward<_Args>(__args)...); @@ -903,7 +903,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) class _Not_fn { template<typename _Fn2, typename... _Args> - using __inv_res_t = result_of_t<_Fn2(_Args&&...)>; + using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type; template<typename _Tp> static decltype(!std::declval<_Tp>()) diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 76865f4..7d067ca 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2392,59 +2392,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 2219. INVOKE-ing a pointer to member with a reference_wrapper // as the object expression - template<typename _Res, typename _Class, typename _Arg> - struct __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>> - : __result_of_memobj_ref<_Res _Class::*, _Arg&> - { }; - - template<typename _Res, typename _Class, typename _Arg> - struct __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>&> - : __result_of_memobj_ref<_Res _Class::*, _Arg&> - { }; - - template<typename _Res, typename _Class, typename _Arg> - struct __result_of_memobj<_Res _Class::*, const reference_wrapper<_Arg>&> - : __result_of_memobj_ref<_Res _Class::*, _Arg&> - { }; - - template<typename _Res, typename _Class, typename _Arg> - struct __result_of_memobj<_Res _Class::*, reference_wrapper<_Arg>&&> - : __result_of_memobj_ref<_Res _Class::*, _Arg&> - { }; - - template<typename _Res, typename _Class, typename _Arg> - struct __result_of_memobj<_Res _Class::*, const reference_wrapper<_Arg>&&> - : __result_of_memobj_ref<_Res _Class::*, _Arg&> - { }; - - template<typename _Res, typename _Class, typename _Arg, typename... _Args> - struct __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>, _Args...> - : __result_of_memfun_ref<_Res _Class::*, _Arg&, _Args...> - { }; - - template<typename _Res, typename _Class, typename _Arg, typename... _Args> - struct __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>&, - _Args...> - : __result_of_memfun_ref<_Res _Class::*, _Arg&, _Args...> - { }; - - template<typename _Res, typename _Class, typename _Arg, typename... _Args> - struct __result_of_memfun<_Res _Class::*, const reference_wrapper<_Arg>&, - _Args...> - : __result_of_memfun_ref<_Res _Class::*, _Arg&, _Args...> - { }; - - template<typename _Res, typename _Class, typename _Arg, typename... _Args> - struct __result_of_memfun<_Res _Class::*, reference_wrapper<_Arg>&&, - _Args...> - : __result_of_memfun_ref<_Res _Class::*, _Arg&, _Args...> - { }; + // Used by result_of, invoke etc. to unwrap a reference_wrapper. + template<typename _Tp, typename _Up = typename decay<_Tp>::type> + struct __inv_unwrap + { + using type = _Tp; + }; - template<typename _Res, typename _Class, typename _Arg, typename... _Args> - struct __result_of_memfun<_Res _Class::*, const reference_wrapper<_Arg>&&, - _Args...> - : __result_of_memfun_ref<_Res _Class::*, _Arg&, _Args...> - { }; + template<typename _Tp, typename _Up> + struct __inv_unwrap<_Tp, reference_wrapper<_Up>> + { + using type = _Up&; + }; template<bool, bool, typename _Functor, typename... _ArgTypes> struct __result_of_impl @@ -2454,12 +2413,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _MemPtr, typename _Arg> struct __result_of_impl<true, false, _MemPtr, _Arg> - : public __result_of_memobj<typename decay<_MemPtr>::type, _Arg> + : public __result_of_memobj<typename decay<_MemPtr>::type, + typename __inv_unwrap<_Arg>::type> { }; template<typename _MemPtr, typename _Arg, typename... _Args> struct __result_of_impl<false, true, _MemPtr, _Arg, _Args...> - : public __result_of_memfun<typename decay<_MemPtr>::type, _Arg, _Args...> + : public __result_of_memfun<typename decay<_MemPtr>::type, + typename __inv_unwrap<_Arg>::type, _Args...> { }; // [func.require] paragraph 1 bullet 5: @@ -2481,8 +2442,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type; }; + // __invoke_result (std::invoke_result for C++11) template<typename _Functor, typename... _ArgTypes> - struct result_of<_Functor(_ArgTypes...)> + struct __invoke_result : public __result_of_impl< is_member_object_pointer< typename remove_reference<_Functor>::type @@ -2490,10 +2452,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_member_function_pointer< typename remove_reference<_Functor>::type >::value, - _Functor, _ArgTypes... + _Functor, _ArgTypes... >::type { }; + template<typename _Functor, typename... _ArgTypes> + struct result_of<_Functor(_ArgTypes...)> + : public __invoke_result<_Functor, _ArgTypes...> + { }; + #if __cplusplus > 201103L /// Alias template for aligned_storage template<size_t _Len, size_t _Align = @@ -2781,37 +2748,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif// c++1z or gnu++11 - // __is_callable (std::is_callable for C++11) + // __is_invocable (std::is_invocable for C++11) - template<typename _Result, typename _Ret, typename = __void_t<>> - struct __is_callable_impl : false_type { }; + template<typename _Result, typename _Ret, typename = void> + struct __is_invocable_impl : false_type { }; template<typename _Result, typename _Ret> - struct __is_callable_impl<_Result, _Ret, __void_t<typename _Result::type>> + struct __is_invocable_impl<_Result, _Ret, __void_t<typename _Result::type>> : __or_<is_void<_Ret>, is_convertible<typename _Result::type, _Ret>>::type { }; - template<typename, typename _Ret = void> - struct __is_callable; // not defined - - template<typename _Fn, typename... _ArgTypes, typename _Ret> - struct __is_callable<_Fn(_ArgTypes...), _Ret> - : __is_callable_impl<result_of<_Fn(_ArgTypes...)>, _Ret>::type + template<typename _Fn, typename... _ArgTypes> + struct __is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type { }; - // Used by __invoke and __is_nothrow_callable to unwrap a reference_wrapper. - template<typename _Tp, typename _Up = typename decay<_Tp>::type> - struct __inv_unwrap - { - using type = _Tp; - }; - - template<typename _Tp, typename _Up> - struct __inv_unwrap<_Tp, reference_wrapper<_Up>> - { - using type = _Up&; - }; - template<typename _Fn, typename _Tp, typename... _Args> constexpr bool __call_is_nt(__invoke_memfun_ref) { @@ -2846,21 +2797,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return noexcept(std::declval<_Fn>()(std::declval<_Args>()...)); } - template<typename _ResultOf, typename _Fn, typename... _Args> + template<typename _Result, typename _Fn, typename... _Args> struct __call_is_nothrow : __bool_constant< - std::__call_is_nt<_Fn, _Args...>(typename _ResultOf::__invoke_type{})> + std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{}) + > { }; - // __is_nothrow_callable (std::is_nothrow_callable for C++11) - - template<typename, typename _Ret = void> - struct __is_nothrow_callable; // not defined + template<typename _Fn, typename... _Args> + using __call_is_nothrow_ + = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>; - template<typename _Fn, typename... _Args, typename _Ret> - struct __is_nothrow_callable<_Fn(_Args...), _Ret> - : __and_<__is_callable<_Fn(_Args...), _Ret>, - __call_is_nothrow<result_of<_Fn(_Args...)>, _Fn, _Args...>>::type + // __is_nothrow_invocable (std::is_nothrow_invocable for C++11) + template<typename _Fn, typename... _Args> + struct __is_nothrow_invocable + : __and_<__is_invocable<_Fn, _Args...>, + __call_is_nothrow_<_Fn, _Args...>>::type { }; struct __nonesuch { @@ -2871,36 +2823,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #if __cplusplus > 201402L -# define __cpp_lib_is_callable 201603 +# define __cpp_lib_is_invocable 201703 + + /// std::invoke_result + template<typename _Functor, typename... _ArgTypes> + struct invoke_result + : public __invoke_result<_Functor, _ArgTypes...> + { }; + + /// std::invoke_result_t + template<typename _Fn, typename... _Args> + using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; - /// std::is_callable - template<typename, typename _Ret = void> - struct is_callable; // not defined + /// std::is_invocable + template<typename _Fn, typename... _ArgTypes> + struct is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type + { }; - template<typename _Fn, typename... _ArgTypes, typename _Ret> - struct is_callable<_Fn(_ArgTypes...), _Ret> - : __is_callable<_Fn(_ArgTypes...), _Ret>::type + /// std::is_invocable_r + template<typename _Ret, typename _Fn, typename... _ArgTypes> + struct is_invocable_r + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type { }; - /// std::is_nothrow_callable - template<typename, typename _Ret = void> - struct is_nothrow_callable; // not defined + /// std::is_nothrow_invocable + template<typename _Fn, typename... _ArgTypes> + struct is_nothrow_invocable + : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { }; - template<typename _Fn, typename... _ArgTypes, typename _Ret> - struct is_nothrow_callable<_Fn(_ArgTypes...), _Ret> - : __is_nothrow_callable<_Fn(_ArgTypes...), _Ret>::type + /// std::is_nothrow_invocable_r + template<typename _Ret, typename _Fn, typename... _ArgTypes> + struct is_nothrow_invocable_r + : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type { }; - /// std::is_callable_v - template<typename _Tp, typename _Ret = void> - constexpr bool is_callable_v = is_callable<_Tp, _Ret>::value; + /// std::is_invocable_v + template<typename _Fn, typename... _Args> + inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; - /// std::is_nothrow_callable_v - template<typename _Tp, typename _Ret = void> - constexpr bool is_nothrow_callable_v - = is_nothrow_callable<_Tp, _Ret>::value; -#endif // C++17 + /// std::is_nothrow_invocable_v + template<typename _Fn, typename... _Args> + inline constexpr bool is_nothrow_invocable_v + = is_nothrow_invocable<_Fn, _Args...>::value; + /// std::is_invocable_r_v + template<typename _Fn, typename... _Args> + inline constexpr bool is_invocable_r_v + = is_invocable_r<_Fn, _Args...>::value; + + /// std::is_nothrow_invocable_r_v + template<typename _Fn, typename... _Args> + inline constexpr bool is_nothrow_invocable_r_v + = is_nothrow_invocable_r<_Fn, _Args...>::value; +#endif // C++17 #if __cplusplus > 201402L # define __cpp_lib_type_trait_variable_templates 201510L diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 0cc50d0..46d7b92 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1236,7 +1236,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { size_t operator()(const variant<_Types...>& __t) const - noexcept((is_nothrow_callable_v<hash<decay_t<_Types>>(_Types)> && ...)) + noexcept((is_nothrow_invocable_v<hash<decay_t<_Types>>, _Types> && ...)) { if (!__t.valueless_by_exception()) { diff --git a/libstdc++-v3/testsuite/20_util/function_objects/invoke/59768.cc b/libstdc++-v3/testsuite/20_util/function_objects/invoke/59768.cc index 2536d22..823e9e0 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/invoke/59768.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/invoke/59768.cc @@ -35,9 +35,3 @@ test01() std::invoke(&A::foo, refc, 100); // const lvalue std::invoke(&A::foo, std::move(refc), 100); // const rvalue } - -int -main() -{ - test01(); -} diff --git a/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc index 0311d01..f3cae38 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/1.cc @@ -103,7 +103,7 @@ test06() F f; auto notf = std::not_fn(f); using NotF = decltype(notf); - static_assert( std::is_callable<NotF()>::value, "cannot negate" ); + static_assert( std::is_invocable<NotF>::value, "cannot negate" ); static_assert( !noexcept(notf()), "conversion to bool affects noexcept" ); } @@ -117,7 +117,7 @@ test07() F f; auto notf = std::not_fn(f); using NotF = decltype(notf); - static_assert( !std::is_callable<NotF()>::value, "cannot negate" ); + static_assert( !std::is_invocable<NotF>::value, "cannot negate" ); } int diff --git a/libstdc++-v3/testsuite/20_util/is_callable/value.cc b/libstdc++-v3/testsuite/20_util/is_callable/value.cc deleted file mode 100644 index e0bb815..0000000 --- a/libstdc++-v3/testsuite/20_util/is_callable/value.cc +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (C) 2016-2017 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" } -// { dg-do compile } - -#include <type_traits> - -#ifndef IS_CALLABLE_DEFINED -template<typename T, typename R = void> - constexpr bool is_callable() - { - static_assert(std::is_callable<T, R>::value == std::is_callable_v<T, R>); - return std::is_callable_v<T, R>; - } -#endif - -void test01() -{ - using func_type_v0 = void(*)(); - - static_assert( is_callable< func_type_v0() >(), ""); - static_assert( is_callable< func_type_v0(), void >(), ""); - static_assert( ! is_callable< func_type_v0(), void* >(), ""); - static_assert( ! is_callable< func_type_v0(), int >(), ""); - - static_assert( ! is_callable< func_type_v0(int) >(), ""); - static_assert( ! is_callable< func_type_v0(int), void >(), ""); - static_assert( ! is_callable< func_type_v0(int), void* >(), ""); - static_assert( ! is_callable< func_type_v0(int), int >(), ""); - - using func_type_i0 = int(*)(); - - static_assert( is_callable< func_type_i0() >(), ""); - static_assert( is_callable< func_type_i0(), void >(), ""); - static_assert( is_callable< func_type_i0(), int >(), ""); - static_assert( ! is_callable< func_type_i0(), int& >(), ""); - static_assert( is_callable< func_type_i0(), long >(), ""); - - static_assert( ! is_callable< func_type_i0(int) >(), ""); - static_assert( ! is_callable< func_type_i0(int), void >(), ""); - static_assert( ! is_callable< func_type_i0(int), int >(), ""); - static_assert( ! is_callable< func_type_i0(int), int& >(), ""); - static_assert( ! is_callable< func_type_i0(int), long >(), ""); - - using func_type_l0 = int&(*)(); - - static_assert( is_callable< func_type_l0() >(), ""); - static_assert( is_callable< func_type_l0(), void >(), ""); - static_assert( is_callable< func_type_l0(), int >(), ""); - static_assert( is_callable< func_type_l0(), int& >(), ""); - static_assert( ! is_callable< func_type_l0(), int&& >(), ""); - static_assert( is_callable< func_type_l0(), long >(), ""); - static_assert( ! is_callable< func_type_l0(), long& >(), ""); - - static_assert( ! is_callable< func_type_l0(int) >(), ""); - static_assert( ! is_callable< func_type_l0(int), void >(), ""); - static_assert( ! is_callable< func_type_l0(int), int >(), ""); - static_assert( ! is_callable< func_type_l0(int), int& >(), ""); - static_assert( ! is_callable< func_type_l0(int), long >(), ""); - - using func_type_ii = int(*)(int); - - static_assert( ! is_callable< func_type_ii() >(), ""); - static_assert( ! is_callable< func_type_ii(), int >(), ""); - static_assert( ! is_callable< func_type_ii(), int& >(), ""); - static_assert( ! is_callable< func_type_ii(), long >(), ""); - - static_assert( is_callable< func_type_ii(int) >(), ""); - static_assert( is_callable< func_type_ii(int), int >(), ""); - static_assert( ! is_callable< func_type_ii(int), int& >(), ""); - static_assert( is_callable< func_type_ii(int), long >(), ""); - - using func_type_il = int(*)(int&); - - static_assert( ! is_callable< func_type_il() >(), ""); - - static_assert( ! is_callable< func_type_il(int) >(), ""); - static_assert( ! is_callable< func_type_il(int), int >(), ""); - static_assert( ! is_callable< func_type_il(int), int& >(), ""); - static_assert( ! is_callable< func_type_il(int), long >(), ""); - - static_assert( is_callable< func_type_il(int&) >(), ""); - static_assert( is_callable< func_type_il(int&), int >(), ""); - static_assert( ! is_callable< func_type_il(int&), int& >(), ""); - static_assert( is_callable< func_type_il(int&), long >(), ""); - - using func_type_ir = int(*)(int&&); - - static_assert( ! is_callable< func_type_ir() >(), ""); - - static_assert( is_callable< func_type_ir(int) >(), ""); - static_assert( is_callable< func_type_ir(int), int >(), ""); - static_assert( ! is_callable< func_type_ir(int), int& >(), ""); - static_assert( is_callable< func_type_ir(int), long >(), ""); - - static_assert( ! is_callable< func_type_ir(int&) >(), ""); - static_assert( ! is_callable< func_type_ir(int&), int >(), ""); - static_assert( ! is_callable< func_type_ir(int&), int& >(), ""); - static_assert( ! is_callable< func_type_ir(int&), long >(), ""); - - struct X { }; - - using mem_type_i = int X::*; - - static_assert( ! is_callable< mem_type_i() >(), ""); - - static_assert( ! is_callable< mem_type_i(int) >(), ""); - static_assert( ! is_callable< mem_type_i(int), int >(), ""); - static_assert( ! is_callable< mem_type_i(int), int& >(), ""); - static_assert( ! is_callable< mem_type_i(int), long >(), ""); - - static_assert( ! is_callable< mem_type_i(int&) >(), ""); - static_assert( ! is_callable< mem_type_i(int&), int >(), ""); - static_assert( ! is_callable< mem_type_i(int&), int& >(), ""); - static_assert( ! is_callable< mem_type_i(int&), long >(), ""); - - static_assert( is_callable< mem_type_i(X&) >(), ""); - static_assert( is_callable< mem_type_i(X&), int >(), ""); - static_assert( is_callable< mem_type_i(X&), int& >(), ""); - static_assert( is_callable< mem_type_i(X&), long >(), ""); - - using memfun_type_i = int (X::*)(); - - static_assert( ! is_callable< memfun_type_i() >(), ""); - - static_assert( ! is_callable< memfun_type_i(int) >(), ""); - - static_assert( ! is_callable< memfun_type_i(int&) >(), ""); - - static_assert( is_callable< memfun_type_i(X&) >(), ""); - static_assert( is_callable< memfun_type_i(X&), int >(), ""); - static_assert( ! is_callable< memfun_type_i(X&), int& >(), ""); - static_assert( is_callable< memfun_type_i(X&), long >(), ""); - static_assert( is_callable< memfun_type_i(X*) >(), ""); - - static_assert( ! is_callable< memfun_type_i(const X&) >(), ""); - static_assert( ! is_callable< memfun_type_i(const X&), int >(), ""); - static_assert( ! is_callable< memfun_type_i(X&, int) >(), ""); - - using memfun_type_iic = int& (X::*)(int&) const; - - static_assert( ! is_callable< memfun_type_iic() >(), ""); - static_assert( ! is_callable< memfun_type_iic(int) >(), ""); - static_assert( ! is_callable< memfun_type_iic(int&) >(), ""); - static_assert( ! is_callable< memfun_type_iic(X&, int) >(), ""); - static_assert( ! is_callable< memfun_type_iic(const X&, int) >(), ""); - static_assert( ! is_callable< memfun_type_iic(const X&, int&, int) >(), ""); - - static_assert( is_callable< memfun_type_iic(const X&, int&) >(), ""); - static_assert( is_callable< memfun_type_iic(const X&, int&), int >(), ""); - static_assert( is_callable< memfun_type_iic(const X&, int&), int& >(), ""); - static_assert( is_callable< memfun_type_iic(const X&, int&), long >(), ""); - static_assert( ! is_callable< memfun_type_iic(const X&, int&), long& >(),""); - static_assert( is_callable< memfun_type_iic(const X*, int&) >(), ""); - - struct F { - int& operator()(); - long& operator()() const; - short& operator()(int) &&; - char& operator()(int) const&; - private: - void operator()(int, int); - }; - using CF = const F; - - static_assert( is_callable< F(), int& >(), ""); - static_assert( is_callable< F&(), int& >(), ""); - static_assert( is_callable< CF(), long& >(), ""); - static_assert( is_callable< CF&(), long& >(), ""); - static_assert( is_callable< F(int), short& >(), ""); - static_assert( is_callable< F&(int), char& >(), ""); - static_assert( is_callable< CF(int), char& >(), ""); - static_assert( is_callable< CF&(int), char& >(), ""); - - static_assert( ! is_callable< F(int, int) >(), ""); -} diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/explicit_instantiation.cc index e1d6384..da4d480 100644 --- a/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation.cc +++ b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/explicit_instantiation.cc @@ -25,5 +25,6 @@ namespace std { struct test_type { }; - template struct is_callable<test_type(), int>; + template struct is_invocable<test_type>; + template struct is_invocable_r<int, test_type>; } diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation_ext.cc b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/explicit_instantiation_ext.cc index b55ce7a..d91d765 100644 --- a/libstdc++-v3/testsuite/20_util/is_callable/requirements/explicit_instantiation_ext.cc +++ b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/explicit_instantiation_ext.cc @@ -24,5 +24,5 @@ namespace std { struct test_type { }; - template struct __is_callable<test_type(), int>; + template struct __is_invocable<test_type>; } diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/typedefs.cc index 35ffdbb..9b42080 100644 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs.cc +++ b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/typedefs.cc @@ -25,6 +25,13 @@ void test01() { // Check for required typedefs - typedef std::is_nothrow_callable<int(), void> test_type; + typedef std::is_invocable<int> test_type; + static_assert( std::is_base_of_v<std::false_type, test_type> ); +} + +void test02() +{ + // Check for required typedefs + typedef std::is_invocable_r<void, int> test_type; static_assert( std::is_base_of_v<std::false_type, test_type> ); } diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs_ext.cc b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/typedefs_ext.cc index 09ba06e..10d4f9d 100644 --- a/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs_ext.cc +++ b/libstdc++-v3/testsuite/20_util/is_invocable/requirements/typedefs_ext.cc @@ -24,6 +24,6 @@ void test01() { // Check for required typedefs - typedef std::__is_callable<int(), void> test_type; + typedef std::__is_invocable<int> test_type; static_assert( std::is_base_of<std::false_type, test_type>::value, "" ); } diff --git a/libstdc++-v3/testsuite/20_util/is_invocable/value.cc b/libstdc++-v3/testsuite/20_util/is_invocable/value.cc new file mode 100644 index 0000000..adfa879 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_invocable/value.cc @@ -0,0 +1,200 @@ +// Copyright (C) 2016-2017 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" } +// { dg-do compile } + +#include <type_traits> + +#ifndef IS_INVOCABLE_DEFINED +template<typename... T> + constexpr bool is_invocable() + { + constexpr bool result = std::is_invocable_v<T...>; + static_assert(std::is_invocable<T...>::value == result); + return result; + } + +template<typename R, typename... T> + constexpr bool is_invocable_r() + { + constexpr bool result = std::is_invocable_r_v<R, T...>; + static_assert(std::is_invocable_r<R, T...>::value == result); + return result; + } +#endif + +void test01() +{ + using func_type_v0 = void(*)(); + + static_assert( is_invocable< func_type_v0 >(), ""); + static_assert( is_invocable_r<void, func_type_v0 >(), ""); + static_assert( ! is_invocable_r<void*, func_type_v0 >(), ""); + static_assert( ! is_invocable_r<int, func_type_v0 >(), ""); + + static_assert( ! is_invocable< func_type_v0, int >(), ""); + static_assert( ! is_invocable_r< void, func_type_v0, int >(), ""); + static_assert( ! is_invocable_r< void*, func_type_v0, int >(), ""); + static_assert( ! is_invocable_r< int, func_type_v0, int >(), ""); + + using func_type_i0 = int(*)(); + + static_assert( is_invocable< func_type_i0 >(), ""); + static_assert( is_invocable_r<void, func_type_i0 >(), ""); + static_assert( is_invocable_r<int, func_type_i0 >(), ""); + static_assert( ! is_invocable_r<int&, func_type_i0 >(), ""); + static_assert( is_invocable_r<long, func_type_i0 >(), ""); + + static_assert( ! is_invocable< func_type_i0, int >(), ""); + static_assert( ! is_invocable_r< void, func_type_i0, int >(), ""); + static_assert( ! is_invocable_r< int, func_type_i0, int >(), ""); + static_assert( ! is_invocable_r< int&, func_type_i0, int >(), ""); + static_assert( ! is_invocable_r< long, func_type_i0, int >(), ""); + + using func_type_l0 = int&(*)(); + + static_assert( is_invocable< func_type_l0 >(), ""); + static_assert( is_invocable_r< void, func_type_l0 >(), ""); + static_assert( is_invocable_r< int, func_type_l0 >(), ""); + static_assert( is_invocable_r< int&, func_type_l0 >(), ""); + static_assert( ! is_invocable_r< int&&, func_type_l0 >(), ""); + static_assert( is_invocable_r< long, func_type_l0 >(), ""); + static_assert( ! is_invocable_r< long&, func_type_l0 >(), ""); + + static_assert( ! is_invocable< func_type_l0(int) >(), ""); + static_assert( ! is_invocable_r< void, func_type_l0, int >(), ""); + static_assert( ! is_invocable_r< int, func_type_l0, int >(), ""); + static_assert( ! is_invocable_r< int&, func_type_l0, int >(), ""); + static_assert( ! is_invocable_r< long, func_type_l0, int >(), ""); + + using func_type_ii = int(*)(int); + + static_assert( ! is_invocable< func_type_ii >(), ""); + static_assert( ! is_invocable_r< int, func_type_ii >(), ""); + static_assert( ! is_invocable_r< int&, func_type_ii >(), ""); + static_assert( ! is_invocable_r< long, func_type_ii >(), ""); + + static_assert( is_invocable< func_type_ii, int >(), ""); + static_assert( is_invocable_r< int, func_type_ii, int >(), ""); + static_assert( ! is_invocable_r< int&, func_type_ii, int >(), ""); + static_assert( is_invocable_r< long, func_type_ii, int >(), ""); + + using func_type_il = int(*)(int&); + + static_assert( ! is_invocable< func_type_il >(), ""); + + static_assert( ! is_invocable< func_type_il, int >(), ""); + static_assert( ! is_invocable_r< int, func_type_il, int >(), ""); + static_assert( ! is_invocable_r< int&, func_type_il, int >(), ""); + static_assert( ! is_invocable_r< long, func_type_il, int >(), ""); + + static_assert( is_invocable< func_type_il, int& >(), ""); + static_assert( is_invocable_r< int, func_type_il, int& >(), ""); + static_assert( ! is_invocable_r< int&, func_type_il, int& >(), ""); + static_assert( is_invocable_r< long, func_type_il, int& >(), ""); + + using func_type_ir = int(*)(int&&); + + static_assert( ! is_invocable< func_type_ir >(), ""); + + static_assert( is_invocable< func_type_ir, int >(), ""); + static_assert( is_invocable_r< int, func_type_ir, int >(), ""); + static_assert( ! is_invocable_r< int&, func_type_ir, int >(), ""); + static_assert( is_invocable_r< long, func_type_ir, int >(), ""); + + static_assert( ! is_invocable< func_type_ir, int& >(), ""); + static_assert( ! is_invocable_r< int, func_type_ir, int& >(), ""); + static_assert( ! is_invocable_r< int&, func_type_ir, int& >(), ""); + static_assert( ! is_invocable_r< long, func_type_ir, int& >(), ""); + + struct X { }; + + using mem_type_i = int X::*; + + static_assert( ! is_invocable< mem_type_i >(), ""); + + static_assert( ! is_invocable< mem_type_i, int >(), ""); + static_assert( ! is_invocable_r< int, mem_type_i, int >(), ""); + static_assert( ! is_invocable_r< int&, mem_type_i, int >(), ""); + static_assert( ! is_invocable_r< long, mem_type_i, int >(), ""); + + static_assert( ! is_invocable< mem_type_i, int& >(), ""); + static_assert( ! is_invocable_r< int, mem_type_i, int& >(), ""); + static_assert( ! is_invocable_r< int&, mem_type_i, int& >(), ""); + static_assert( ! is_invocable_r< long, mem_type_i, int& >(), ""); + + static_assert( is_invocable< mem_type_i, X& >(), ""); + static_assert( is_invocable_r< int, mem_type_i, X& >(), ""); + static_assert( is_invocable_r< int&, mem_type_i, X& >(), ""); + static_assert( is_invocable_r< long, mem_type_i, X& >(), ""); + + using memfun_type_i = int (X::*)(); + + static_assert( ! is_invocable< memfun_type_i >(), ""); + + static_assert( ! is_invocable< memfun_type_i, int >(), ""); + + static_assert( ! is_invocable< memfun_type_i, int& >(), ""); + + static_assert( is_invocable< memfun_type_i, X& >(), ""); + static_assert( is_invocable_r< int, memfun_type_i, X& >(), ""); + static_assert( ! is_invocable_r< int&, memfun_type_i, X& >(), ""); + static_assert( is_invocable_r< long, memfun_type_i, X& >(), ""); + static_assert( is_invocable< memfun_type_i, X* >(), ""); + + static_assert( ! is_invocable< memfun_type_i, const X& >(), ""); + static_assert( ! is_invocable_r< int, memfun_type_i, const X& >(), ""); + static_assert( ! is_invocable< memfun_type_i, X&, int >(), ""); + + using memfun_type_iic = int& (X::*)(int&) const; + + static_assert( ! is_invocable< memfun_type_iic >(), ""); + static_assert( ! is_invocable< memfun_type_iic, int >(), ""); + static_assert( ! is_invocable< memfun_type_iic, int& >(), ""); + static_assert( ! is_invocable< memfun_type_iic, X&, int >(), ""); + static_assert( ! is_invocable< memfun_type_iic, const X&, int >(), ""); + static_assert( ! is_invocable< memfun_type_iic, const X&, int&, int >(), ""); + + static_assert( is_invocable< memfun_type_iic, const X&, int& >(), ""); + static_assert( is_invocable_r< int, memfun_type_iic, const X&, int& >(), ""); + static_assert( is_invocable_r< int&, memfun_type_iic, const X&, int& >(), ""); + static_assert( is_invocable_r< long, memfun_type_iic, const X&, int& >(), ""); + static_assert( ! is_invocable_r< long&, memfun_type_iic, const X&, int& >(),""); + static_assert( is_invocable< memfun_type_iic, const X*, int& >(), ""); + + struct F { + int& operator()(); + long& operator()() const; + short& operator()(int) &&; + char& operator()(int) const&; + private: + void operator()(int, int); + }; + using CF = const F; + + static_assert( is_invocable_r< int&, F >(), ""); + static_assert( is_invocable_r< int&, F& >(), ""); + static_assert( is_invocable_r< long&, CF >(), ""); + static_assert( is_invocable_r< long&, CF& >(), ""); + static_assert( is_invocable_r< short&, F, int >(), ""); + static_assert( is_invocable_r< char&, F&, int >(), ""); + static_assert( is_invocable_r< char&, CF, int >(), ""); + static_assert( is_invocable_r< char&, CF&, int >(), ""); + + static_assert( ! is_invocable< F, int, int >(), ""); +} diff --git a/libstdc++-v3/testsuite/20_util/is_callable/value_ext.cc b/libstdc++-v3/testsuite/20_util/is_invocable/value_ext.cc index f7c8be9..d167cfa 100644 --- a/libstdc++-v3/testsuite/20_util/is_callable/value_ext.cc +++ b/libstdc++-v3/testsuite/20_util/is_invocable/value_ext.cc @@ -19,8 +19,22 @@ #include <type_traits> -template<typename T, typename R = void> - constexpr bool is_callable() { return std::__is_callable<T, R>::value; } +template<typename... T> + constexpr bool is_invocable() { return std::__is_invocable<T...>::value; } -#define IS_CALLABLE_DEFINED +template<typename R, typename... T> + constexpr bool is_invocable_conv(std::true_type) + { + using result_type = typename std::__invoke_result<T...>::type; + return std::is_void<R>::value || std::is_convertible<result_type, R>::value; + } + +template<typename R, typename... T> + constexpr bool is_invocable_conv(std::false_type) { return false; } + +template<typename R, typename... T> + constexpr bool is_invocable_r() + { return is_invocable_conv<R, T...>(std::__is_invocable<T...>{}); } + +#define IS_INVOCABLE_DEFINED #include "value.cc" diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value.cc deleted file mode 100644 index 16b55da..0000000 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2016-2017 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" } -// { dg-do compile } - -#include <type_traits> - -#ifndef IS_NT_CALLABLE_DEFINED -template<typename T, typename R = void> - constexpr bool is_nt_callable() - { - static_assert(std::is_nothrow_callable<T, R>::value - == std::is_nothrow_callable_v<T, R>); - return std::is_nothrow_callable_v<T, R>; - } -#endif - -void test01() -{ - using func_type = void(*)(); - static_assert( ! is_nt_callable< func_type() >(), ""); - -#if __cpp_noexcept_function_type - using func_type_nt = void(*)() noexcept; - static_assert( is_nt_callable< func_type_nt() >(), ""); -#endif - - struct X { }; - using mem_type = int X::*; - - static_assert( ! is_nt_callable< mem_type() >(), ""); - static_assert( ! is_nt_callable< mem_type(int) >(), ""); - static_assert( ! is_nt_callable< mem_type(int&) >(), ""); - - static_assert( is_nt_callable< mem_type(X&) >(), ""); - static_assert( is_nt_callable< mem_type(X&), int >(), ""); - static_assert( is_nt_callable< mem_type(X&), int& >(), ""); - static_assert( is_nt_callable< mem_type(X&), long >(), ""); - static_assert( is_nt_callable< mem_type(X*), int& >(), ""); - - using memfun_type = int (X::*)(); - - static_assert( ! is_nt_callable< memfun_type() >(), ""); - static_assert( ! is_nt_callable< memfun_type(int) >(), ""); - static_assert( ! is_nt_callable< memfun_type(int&) >(), ""); - static_assert( ! is_nt_callable< memfun_type(X&) >(), ""); - static_assert( ! is_nt_callable< memfun_type(X*) >(), ""); - -#if __cpp_noexcept_function_type - using memfun_type_nt = int (X::*)() noexcept; - - static_assert( ! is_nt_callable< memfun_type_nt() >(), ""); - static_assert( ! is_nt_callable< memfun_type_nt(int) >(), ""); - static_assert( ! is_nt_callable< memfun_type_nt(int&) >(), ""); - static_assert( is_nt_callable< memfun_type_nt(X&) >(), ""); - static_assert( is_nt_callable< memfun_type_nt(X*) >(), ""); -#endif - - struct F { - int& operator()(); - long& operator()() const noexcept; - short& operator()(int) &&; - char& operator()(int) const& noexcept; - private: - void operator()(int, int) noexcept; - }; - using CF = const F; - - static_assert( ! is_nt_callable< F(), int& >(), ""); - static_assert( is_nt_callable< CF(), long& >(), ""); - static_assert( ! is_nt_callable< F(int), short& >(), ""); - static_assert( is_nt_callable< F&(int), char& >(), ""); - static_assert( is_nt_callable< CF(int), char& >(), ""); - static_assert( is_nt_callable< CF&(int), char& >(), ""); - - static_assert( ! is_nt_callable< F(int, int) >(), ""); -} diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/explicit_instantiation.cc index 996b7d8..0232698 100644 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation.cc +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/explicit_instantiation.cc @@ -25,5 +25,6 @@ namespace std { struct test_type { }; - template struct is_nothrow_callable<test_type(), int>; + template struct is_nothrow_invocable<test_type>; + template struct is_nothrow_invocable_r<int, test_type>; } diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation_ext.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/explicit_instantiation_ext.cc index 0243f28..f9afed6 100644 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/explicit_instantiation_ext.cc +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/explicit_instantiation_ext.cc @@ -24,5 +24,5 @@ namespace std { struct test_type { }; - template struct __is_nothrow_callable<test_type(), int>; + template struct __is_nothrow_invocable<test_type>; } diff --git a/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/typedefs.cc index c429f95..3b31675 100644 --- a/libstdc++-v3/testsuite/20_util/is_callable/requirements/typedefs.cc +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/typedefs.cc @@ -25,6 +25,13 @@ void test01() { // Check for required typedefs - typedef std::is_callable<int(), void> test_type; + typedef std::is_nothrow_invocable<int> test_type; + static_assert( std::is_base_of_v<std::false_type, test_type> ); +} + +void test02() +{ + // Check for required typedefs + typedef std::is_nothrow_invocable_r<void, int> test_type; static_assert( std::is_base_of_v<std::false_type, test_type> ); } diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs_ext.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/typedefs_ext.cc index 9ba091d..db2ad61 100644 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/requirements/typedefs_ext.cc +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/requirements/typedefs_ext.cc @@ -24,6 +24,6 @@ void test01() { // Check for required typedefs - typedef std::__is_nothrow_callable<int(), void> test_type; + typedef std::__is_nothrow_invocable<int> test_type; static_assert( std::is_base_of<std::false_type, test_type>::value, "" ); } diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/value.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/value.cc new file mode 100644 index 0000000..4ccb459 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/value.cc @@ -0,0 +1,100 @@ +// Copyright (C) 2016-2017 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" } +// { dg-do compile } + +#include <type_traits> + +#ifndef IS_NT_INVOCABLE_DEFINED +template<typename... T> + constexpr bool is_nt_invocable() + { + constexpr bool result = std::is_nothrow_invocable_v<T...>; + static_assert(std::is_nothrow_invocable<T...>::value == result); + return result; + } + +template<typename R, typename... T> + constexpr bool is_nt_invocable_r() + { + constexpr bool result = std::is_nothrow_invocable_r_v<R, T...>; + static_assert(std::is_nothrow_invocable_r<R, T...>::value == result); + return result; + } +#endif + +void test01() +{ + using func_type = void(*)(); + static_assert( ! is_nt_invocable< func_type>(), ""); + +#if __cpp_noexcept_function_type + using func_type_nt = void(*)() noexcept; + static_assert( is_nt_invocable< func_type_nt >(), ""); +#endif + + struct X { }; + using mem_type = int X::*; + + static_assert( ! is_nt_invocable< mem_type >(), ""); + static_assert( ! is_nt_invocable< mem_type, int >(), ""); + static_assert( ! is_nt_invocable< mem_type, int& >(), ""); + + static_assert( is_nt_invocable< mem_type, X& >(), ""); + static_assert( is_nt_invocable_r< int, mem_type, X& >(), ""); + static_assert( is_nt_invocable_r< int&, mem_type, X& >(), ""); + static_assert( is_nt_invocable_r< long, mem_type, X& >(), ""); + static_assert( is_nt_invocable_r< int&, mem_type, X* >(), ""); + + using memfun_type = int (X::*)(); + + static_assert( ! is_nt_invocable< memfun_type >(), ""); + static_assert( ! is_nt_invocable< memfun_type, int >(), ""); + static_assert( ! is_nt_invocable< memfun_type, int& >(), ""); + static_assert( ! is_nt_invocable< memfun_type, X& >(), ""); + static_assert( ! is_nt_invocable< memfun_type, X* >(), ""); + +#if __cpp_noexcept_function_type + using memfun_type_nt = int (X::*)() noexcept; + + static_assert( ! is_nt_invocable< memfun_type_nt >(), ""); + static_assert( ! is_nt_invocable< memfun_type_nt, int >(), ""); + static_assert( ! is_nt_invocable< memfun_type_nt, int& >(), ""); + static_assert( is_nt_invocable< memfun_type_nt, X& >(), ""); + static_assert( is_nt_invocable< memfun_type_nt, X* >(), ""); +#endif + + struct F { + int& operator()(); + long& operator()() const noexcept; + short& operator()(int) &&; + char& operator()(int) const& noexcept; + private: + void operator()(int, int) noexcept; + }; + using CF = const F; + + static_assert( ! is_nt_invocable_r< int&, F >(), ""); + static_assert( is_nt_invocable_r< long&, CF >(), ""); + static_assert( ! is_nt_invocable_r< short&, F, int >(), "" ); + static_assert( is_nt_invocable_r< char&, F&, int >(), "" ); + static_assert( is_nt_invocable_r< char&, CF, int >(), "" ); + static_assert( is_nt_invocable_r< char&, CF&, int >(), "" ); + + static_assert( ! is_nt_invocable< F, int, int >(), ""); +} diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value_ext.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/value_ext.cc index 987e52b..7217324 100644 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_callable/value_ext.cc +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/value_ext.cc @@ -19,9 +19,25 @@ #include <type_traits> -template<typename T, typename R = void> - constexpr bool is_nt_callable() - { return std::__is_nothrow_callable<T, R>::value; } +template<typename... T> + constexpr bool is_nt_invocable() + { return std::__is_nothrow_invocable<T...>::value; } -#define IS_NT_CALLABLE_DEFINED + template<typename R, typename... T> + constexpr bool is_nt_invocable_conv(std::true_type) + { + using result_type = typename std::__invoke_result<T...>::type; + return std::is_void<R>::value || std::is_convertible<result_type, R>::value; + } + +template<typename R, typename... T> + constexpr bool is_nt_invocable_conv(std::false_type) { return false; } + +template<typename R, typename... T> + constexpr bool is_nt_invocable_r() + { + return is_nt_invocable_conv<R, T...>(std::__is_nothrow_invocable<T...>{}); + } + +#define IS_NT_INVOCABLE_DEFINED #include "value.cc" diff --git a/libstdc++-v3/testsuite/20_util/optional/hash.cc b/libstdc++-v3/testsuite/20_util/optional/hash.cc index 297ea2e..c16f0b2 100644 --- a/libstdc++-v3/testsuite/20_util/optional/hash.cc +++ b/libstdc++-v3/testsuite/20_util/optional/hash.cc @@ -29,12 +29,10 @@ template<class T> auto f(...) -> decltype(std::false_type()); static_assert(!decltype(f<S>(0))::value, ""); -static_assert(!std::is_callable< - std::hash<std::optional<S>>& - (std::optional<S> const&)>::value, ""); -static_assert(std::is_callable< - std::hash<std::optional<int>>& - (std::optional<int> const&)>::value, ""); +static_assert(!std::is_invocable_v< + std::hash<std::optional<S>>&, std::optional<S> const&> ); +static_assert(std::is_invocable_v< + std::hash<std::optional<int>>&, std::optional<int> const&> ); int main() { diff --git a/libstdc++-v3/testsuite/20_util/variant/hash.cc b/libstdc++-v3/testsuite/20_util/variant/hash.cc index 0a267ab..d747e10 100644 --- a/libstdc++-v3/testsuite/20_util/variant/hash.cc +++ b/libstdc++-v3/testsuite/20_util/variant/hash.cc @@ -33,17 +33,14 @@ static_assert(!decltype(f<std::variant<S>>(0))::value, ""); static_assert(!decltype(f<std::variant<S, S>>(0))::value, ""); static_assert(decltype(f<std::variant<int>>(0))::value, ""); static_assert(decltype(f<std::variant<int, int>>(0))::value, ""); -static_assert(!std::is_callable< - std::hash<std::variant<S>>&(std::variant<S> const&)>::value, ""); -static_assert(!std::is_callable< - std::hash<std::variant<S, int>>& - (std::variant<S, int> const&)>::value, ""); -static_assert(std::is_callable< - std::hash<std::variant<int>>& - (std::variant<int> const&)>::value, ""); -static_assert(std::is_callable< - std::hash<std::variant<int, int>>& - (std::variant<int, int> const&)>::value, ""); +static_assert(!std::is_invocable_v< + std::hash<std::variant<S>>&, std::variant<S> const&> ); +static_assert(!std::is_invocable_v< + std::hash<std::variant<S, int>>&, std::variant<S, int> const&> ); +static_assert(std::is_invocable_v< + std::hash<std::variant<int>>&, std::variant<int> const&> ); +static_assert(std::is_invocable_v< + std::hash<std::variant<int, int>>&, std::variant<int, int> const&> ); int main() { |