使用 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.
#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';
}
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
.
根据 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 overloadedoperator()
and pointers to functions don't count as function types.
#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';
}
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
.