使用 cv 限定符和 ref 限定符实现 std::is_function

Implementation of std::is_function with cv-qualifiers and ref-qualifiers

根据 C++ reference,这是 std::is_function 的有效实现(不包括可变参数函数的部分特化和 noexcept 简洁说明符):

template<class>
struct is_function : std::false_type { };
 
// specialization for regular functions
template<class Ret, class... Args>
struct is_function<Ret(Args...)> : std::true_type {};
 
// specialization for function types that have cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...)const> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)const volatile> : std::true_type {};
 
// specialization for function types that have ref-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)const &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)const volatile &> : std::true_type {};
struct is_function<Ret(Args...) &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)const &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)volatile &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...)const volatile &&> : std::true_type {};

但是,在成员函数上使用 std::is_function returns false:

struct X
{
    int Test(float)
    {
        return 0;
    }
};

int main()
{
    auto x = std::is_function_v<decltype(&X::Test)>; // x is 'false'
    return 0;
}

据我了解,cv-qualifiers 和 ref-qualifiers 仅适用于 class 成员函数。

所以我的问题是,为什么 std::is_function 的实现在不考虑成员函数“函数”的情况下专门针对所有不同的 cv 限定符和 ref 限定符?

更新:

根据下面的回答,我决定做一个实验。我实现了自己的最小版本 std::is_function:

template <class T>
struct IsFunction :
    std::integral_constant<bool, false>
{
};

template <class R, class... A>
struct IsFunction<R(A...)> :
    std::integral_constant<bool, true>
{
};

template <class T>
constexpr bool IsFunctionV = IsFunction<T>::value;

然后我更改了X::Test的签名:

struct X
{
    int Test(float) const
    {
        return 0;
    }
};

使用答案中提供的 function_traits 结构,然后我尝试了这个:

auto x = IsFunctionV<function_traits<decltype(&X::Test)>::type>;

在这种情况下,x 为假。但是,如果我将 const 的专业化添加到我的 IsFunction 中:

template <class R, class... A>
struct IsFunction<R(A...) const> :
    std::integral_constant<bool, true>
{
};

那么x就会!所以过载很重要。但是我不确定我是否理解为什么 function_traits 最终将“成员函数指针”转换为“成员函数”,这与常规函数并不完全相同,是吗... ?

这不是问题的直接答案,而是展示了如何从成员函数类型中删除 class。


您可以通过简单的类型特征从成员函数中删除 class 实例,使函数与 is_function 兼容。这显然是必要的,因为

Types like std::function, lambdas, classes with overloaded operator()and pointers to functions don't count as function types.

http://en.cppreference.com/w/cpp/types/is_function

#include <iostream>
#include <type_traits>

template < typename T >
struct function_traits { typedef T type; };

template < typename T, typename C >
struct function_traits < T(C::*) > { typedef T type; };

struct X
{
    int Test(float)
    {
        return 0;
    }
};

int test(float) { return 1; }

int main()
{
    std::cout << std::boolalpha;

    auto x = std::is_function< decltype(&X::Test) >::value;
    std::cout << x << '\n';

    auto y = std::is_function< function_traits<decltype(&X::Test)>::type >::value;
    std::cout << y << '\n';

    auto z = std::is_function< function_traits<decltype(test)>::type >::value;
    std::cout << z << '\n';
}

Demo on Wandbox

As far as I understand it, cv-qualifiers and ref-qualifiers are only applicable to class member functions.

虽然非成员函数不能有 cv 限定符或 ref 限定符,但函数类型仍然可以包含它们而无需绑定到特定的 class 类型。

typedef void fc() const;
struct S { fc f; };
void S::f() const { }

这里的std::is_function_v<fc>应该是true.