template<typename _Result, typename _Ret>
struct __is_invocable_impl<_Result, _Ret, __void_t<typename _Result::type>>
- : __or_<is_void<_Ret>, is_convertible<typename _Result::type, _Ret>>::type
+ : is_convertible<typename _Result::type, _Ret>::type
+ { };
+
+ template<typename _Result>
+ struct __is_invocable_impl<_Result, void, __void_t<typename _Result::type>>
+ : true_type
{ };
template<typename _Fn, typename... _ArgTypes>
__call_is_nothrow_<_Fn, _ArgTypes...>>::type
{ };
+ template<typename _Result, typename _Ret, typename = void>
+ struct __is_nt_invocable_impl : false_type { };
+
+ template<typename _Result, typename _Ret>
+ struct __is_nt_invocable_impl<_Result, _Ret,
+ __void_t<typename _Result::type>>
+ : __and_<is_convertible<typename _Result::type, _Ret>,
+ is_nothrow_constructible<_Ret, typename _Result::type>>
+ { };
+
+ template<typename _Result>
+ struct __is_nt_invocable_impl<_Result, void,
+ __void_t<typename _Result::type>>
+ : true_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>,
+ : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>,
__call_is_nothrow_<_Fn, _ArgTypes...>>::type
{ };
void test01()
{
+ struct T { T(int) { } };
+ struct NT { NT(int) noexcept { } };
+ struct Ex { explicit Ex(int) noexcept { } };
+
using func_type = void(*)();
static_assert( ! is_nt_invocable< func_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* >(), "");
+ 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< long&, mem_type, X& >(),
+ "conversion fails, cannot bind long& to int");
+ static_assert( is_nt_invocable_r< int&, mem_type, X* >(), "");
+
+ static_assert( ! is_nt_invocable_r< T, mem_type, X& >(),
+ "conversion throws");
+ static_assert( is_nt_invocable_r< NT, mem_type, X& >(), "");
+ static_assert( ! is_nt_invocable_r< Ex, mem_type, X& >(),
+ "conversion fails, would use explicit constructor");
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* >(), "");
+ static_assert( ! is_nt_invocable< memfun_type >(), "no object");
+ static_assert( ! is_nt_invocable< memfun_type, int >(), "no object");
+ static_assert( ! is_nt_invocable< memfun_type, int& >(), "no object");
+ static_assert( ! is_nt_invocable< memfun_type, X& >(), "call throws");
+ static_assert( ! is_nt_invocable< memfun_type, X* >(), "call throws");
+
+ static_assert( ! is_nt_invocable_r< T, memfun_type, X& >(), "call throws");
+ static_assert( ! is_nt_invocable_r< NT, memfun_type, X& >(), "call throws");
+ static_assert( ! is_nt_invocable_r< Ex, memfun_type, X& >(), "call throws");
#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 >(), "no object");
+ static_assert( ! is_nt_invocable< memfun_type_nt, int >(), "no object");
+ static_assert( ! is_nt_invocable< memfun_type_nt, int& >(), "no object");
static_assert( is_nt_invocable< memfun_type_nt, X& >(), "");
static_assert( is_nt_invocable< memfun_type_nt, X* >(), "");
+
+ static_assert( ! is_nt_invocable_r< T, memfun_type_nt, X& >(),
+ "conversion throws");
+ static_assert( is_nt_invocable_r< NT, memfun_type_nt, X& >(), "");
+ static_assert( ! is_nt_invocable_r< Ex, memfun_type_nt, X& >(),
+ "conversion fails, would use explicit constructor");
#endif
struct F {
};
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 >(), "");
+ static_assert( ! is_nt_invocable< F >(), "call throws");
+ static_assert( is_nt_invocable< CF >(), "");
+
+ static_assert( ! is_nt_invocable_r< int&, F >(), "call throws");
+ static_assert( is_nt_invocable_r< long&, CF >(), "");
+ static_assert( ! is_nt_invocable_r< T, F >(), "call throws");
+ static_assert( ! is_nt_invocable_r< NT, F >(), "call throws");
+ static_assert( ! is_nt_invocable_r< Ex, F >(), "call throws");
+ static_assert( ! is_nt_invocable_r< T, CF >(), "conversion throws");
+ static_assert( is_nt_invocable_r< NT, CF >(), "" );
+ static_assert( ! is_nt_invocable_r< Ex, CF >(), "conversion fails");
+
+ static_assert( ! is_nt_invocable< F, int >(), "call throws");
+ static_assert( is_nt_invocable< F&, int >(), "");
+
+ static_assert( ! is_nt_invocable_r< short&, F, int >(),
+ "call throws" );
+ static_assert( is_nt_invocable_r< char&, F&, int >(), "");
+ static_assert( ! is_nt_invocable_r< T, F&, int >(),
+ "conversion throws");
+ static_assert( is_nt_invocable_r< NT, F&, int >(), "");
+ static_assert( ! is_nt_invocable_r< Ex, F&, int >(),
+ "conversion fails, would use explicit constructor");
+
+ static_assert( is_nt_invocable< CF, int >(), "");
+ static_assert( is_nt_invocable< CF&, int >(), "");
+
+ static_assert( is_nt_invocable_r< char&, CF, int >(), "");
+ static_assert( is_nt_invocable_r< char&, CF&, int >(), "");
+
+ static_assert( ! is_nt_invocable_r< T, CF&, int >(),
+ "conversion throws");
+ static_assert( is_nt_invocable_r< NT, CF&, int >(), "");
+ static_assert( ! is_nt_invocable_r< Ex, CF&, int >(),
+ "conversion fails, would use explicit constructor");
+
+ static_assert( ! is_nt_invocable< F, int, int >(),
+ "would call private member");
+ static_assert( ! is_nt_invocable_r<void, F, int, int >(),
+ "would call private member");
}