Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -430,9 +430,12 @@ namespace __libcpp_is_function_imp { +struct __dummy_type {}; template char __test(_Tp*); +template char __test(__dummy_type); template __two __test(...); -template _Tp& __source(); +template _Tp& __source(int); +template __dummy_type __source(long); } template ::value || @@ -441,7 +444,7 @@ is_reference<_Tp>::value || __is_nullptr_t<_Tp>::value > struct __libcpp_is_function - : public integral_constant(__libcpp_is_function_imp::__source<_Tp>())) == 1> + : public integral_constant(__libcpp_is_function_imp::__source<_Tp>(0))) == 1> {}; template struct __libcpp_is_function<_Tp, true> : public false_type {}; Index: test/std/utilities/meta/meta.unary/meta.unary.cat/function.pass.cpp =================================================================== --- test/std/utilities/meta/meta.unary/meta.unary.cat/function.pass.cpp +++ test/std/utilities/meta/meta.unary/meta.unary.cat/function.pass.cpp @@ -13,8 +13,19 @@ #include +using namespace std; + +class Class {}; + +enum Enum1 {}; +#if __cplusplus >= 201103L +enum class Enum2 : int {}; +#else +enum Enum2 {}; +#endif + template -void test_function_imp() +void test() { static_assert(!std::is_void::value, ""); #if _LIBCPP_STD_VER > 11 @@ -34,19 +45,104 @@ static_assert( std::is_function::value, ""); } +// This function checks that we actually get to the SFINAE test in +// __libcpp_is_function and check that it fails. template -void test_function() +void test_sfinae_failure() { - test_function_imp(); - test_function_imp(); - test_function_imp(); - test_function_imp(); + // Check that we get the overload of __libcpp_is_function that + // evaluates the sfinae + static_assert(!std::is_class::value, ""); + static_assert(!std::is_union::value, ""); + static_assert(!std::is_void::value, ""); + static_assert(!std::is_reference::value, ""); + static_assert(!std::__is_nullptr_t::value, ""); + // Check that the trait actually works + static_assert(!std::is_function::value, ""); } +// Since we can't actually add the const volatile and ref qualifiers once +// later let's use a macro to do it. +#define TEST_REGULAR(...) \ + test<__VA_ARGS__>(); \ + test<__VA_ARGS__ const>(); \ + test<__VA_ARGS__ volatile>(); \ + test<__VA_ARGS__ const volatile>() + +#define TEST_REF_QUALIFIED(...) \ + test<__VA_ARGS__ &>(); \ + test<__VA_ARGS__ const &>(); \ + test<__VA_ARGS__ volatile &>(); \ + test<__VA_ARGS__ const volatile &>(); \ + test<__VA_ARGS__ &&>(); \ + test<__VA_ARGS__ const &&>(); \ + test<__VA_ARGS__ volatile &&>(); \ + test<__VA_ARGS__ const volatile &&>() + +#define TEST_SFINAE_FAILURE(...) \ + test_sfinae_failure<__VA_ARGS__>(); \ + test_sfinae_failure<__VA_ARGS__ const>(); \ + test_sfinae_failure<__VA_ARGS__ volatile>(); \ + test_sfinae_failure<__VA_ARGS__ const volatile>() + +#define TEST_MEM_FN_REF(...) \ + test_sfinae_failure<__VA_ARGS__ &>(); \ + test_sfinae_failure<__VA_ARGS__ const &>(); \ + test_sfinae_failure<__VA_ARGS__ volatile &>(); \ + test_sfinae_failure<__VA_ARGS__ const volatile &>(); \ + test_sfinae_failure<__VA_ARGS__ &&>(); \ + test_sfinae_failure<__VA_ARGS__ const &&>(); \ + test_sfinae_failure<__VA_ARGS__ volatile &&>(); \ + test_sfinae_failure<__VA_ARGS__ const volatile &&>() + int main() { - test_function(); - test_function(); - test_function(); - test_function(); + TEST_REGULAR( void () ); + TEST_REGULAR( void (int) ); + TEST_REGULAR( int (double) ); + TEST_REGULAR( int (double, char) ); + TEST_REGULAR( void (...) ); + TEST_REGULAR( void (int, ...) ); + TEST_REGULAR( int (double, ...) ); + TEST_REGULAR( int (double, char, ...) ); +#if __cplusplus >= 201103L + TEST_REF_QUALIFIED( void () ); + TEST_REF_QUALIFIED( void (int) ); + TEST_REF_QUALIFIED( int (double) ); + TEST_REF_QUALIFIED( int (double, char) ); + TEST_REF_QUALIFIED( void (...) ); + TEST_REF_QUALIFIED( void (int, ...) ); + TEST_REF_QUALIFIED( int (double, ...) ); + TEST_REF_QUALIFIED( int (double, char, ...) ); +#endif + + TEST_SFINAE_FAILURE( int ); + TEST_SFINAE_FAILURE( int* ); + TEST_SFINAE_FAILURE( int const* ); + TEST_SFINAE_FAILURE( int volatile* ); + TEST_SFINAE_FAILURE( int const volatile* ); + TEST_SFINAE_FAILURE( void* ); + TEST_SFINAE_FAILURE( Enum1 ); + TEST_SFINAE_FAILURE( Enum1* ); + TEST_SFINAE_FAILURE( Enum2 ); + TEST_SFINAE_FAILURE( Enum2* ); + + TEST_SFINAE_FAILURE( void (Class::*)() ); + TEST_SFINAE_FAILURE( void (Class::*)(int) ); + TEST_SFINAE_FAILURE( int (Class::*)(double) ); + TEST_SFINAE_FAILURE( int (Class::*)(double, char) ); + TEST_SFINAE_FAILURE( void (Class::*)(...) ); + TEST_SFINAE_FAILURE( void (Class::*)(int, ...) ); + TEST_SFINAE_FAILURE( int (Class::*)(double, ...) ); + TEST_SFINAE_FAILURE( int (Class::*)(double, char, ...) ); +#if __cplusplus >= 201103L + TEST_MEM_FN_REF( void (Class::*)() ); + TEST_MEM_FN_REF( void (Class::*)(int) ); + TEST_MEM_FN_REF( int (Class::*)(double) ); + TEST_MEM_FN_REF( int (Class::*)(double, char) ); + TEST_MEM_FN_REF( void (Class::*)(...) ); + TEST_MEM_FN_REF( void (Class::*)(int, ...) ); + TEST_MEM_FN_REF( int (Class::*)(double, ...) ); + TEST_MEM_FN_REF( int (Class::*)(double, char, ...) ); +#endif }