Index: libcxx/include/type_traits =================================================================== --- libcxx/include/type_traits +++ libcxx/include/type_traits @@ -4382,6 +4382,19 @@ static const bool value = type::value; }; +template +struct _LIBCPP_TEMPLATE_VIS __invokable_r<_Ret, void, _Args...> : public false_type {}; + +template +struct _LIBCPP_TEMPLATE_VIS __invokable_r<_Ret, const void, _Args...> : public false_type {}; + +template +struct _LIBCPP_TEMPLATE_VIS __invokable_r<_Ret, volatile void, _Args...> : public false_type {}; + +template +struct _LIBCPP_TEMPLATE_VIS __invokable_r<_Ret, const volatile void, _Args...> : public false_type {}; + + template using __invokable = __invokable_r; Index: libcxx/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp =================================================================== --- libcxx/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp +++ libcxx/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp @@ -15,9 +15,14 @@ // Most testing of is_invocable is done within the [meta.trans.other] result_of // tests. +// Fn and all types in the template parameter pack ArgTypes shall be +// complete types, cv void, or arrays of unknown bound. + + #include #include #include +#include #include "test_macros.h" @@ -37,8 +42,69 @@ int operator()(Tag) { return 42; } }; + int main() { +// Non-callable things + { + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + + static_assert(!std::is_invocable>::value, ""); + static_assert(!std::is_invocable>::value, ""); + static_assert(!std::is_invocable>::value, ""); + +// with parameters + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + static_assert(!std::is_invocable::value, ""); + + + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + + static_assert(!std::is_invocable_r>::value, ""); + static_assert(!std::is_invocable_r>::value, ""); + static_assert(!std::is_invocable_r>::value, ""); + +// with parameters + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + static_assert(!std::is_invocable_r::value, ""); + } + { using Fn = int(Tag::*)(int); using RFn = int(Tag::*)(int) &&; Index: libcxx/test/std/utilities/meta/meta.rel/is_nothrow_invocable.pass.cpp =================================================================== --- libcxx/test/std/utilities/meta/meta.rel/is_nothrow_invocable.pass.cpp +++ libcxx/test/std/utilities/meta/meta.rel/is_nothrow_invocable.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "test_macros.h" @@ -73,6 +74,66 @@ int main() { +// Non-callable things + { + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + + static_assert(!std::is_nothrow_invocable>::value, ""); + static_assert(!std::is_nothrow_invocable>::value, ""); + static_assert(!std::is_nothrow_invocable>::value, ""); + +// with parameters + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + static_assert(!std::is_nothrow_invocable::value, ""); + + + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + + static_assert(!std::is_nothrow_invocable_r>::value, ""); + static_assert(!std::is_nothrow_invocable_r>::value, ""); + static_assert(!std::is_nothrow_invocable_r>::value, ""); + +// with parameters + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + static_assert(!std::is_nothrow_invocable_r::value, ""); + } + { // Check that the conversion to the return type is properly checked using Fn = CallObject;