如何检测具有特定签名的静态成员函数的存在
How to detect the presence of a static member function with certain signature?
我发现了几个问题&关于SO的答案涉及在编译时(通过SFINAE)检测给定类是否具有特定名称、类型或签名的成员。然而,我找不到一个也适用于静态公共成员函数的函数(当指向成员的指针技巧不起作用时)。有什么想法吗?
以下内容可能会有所帮助:(https://ideone.com/nDlFUE)
#include <cstdint>
#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)
template <typename U>
class traitsName
{
private:
template<typename T, T> struct helper;
template<typename T>
static std::uint8_t check(helper<signature, &funcName>*);
template<typename T> static std::uint16_t check(...);
public:
static
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t);
}
然后定义一个特征:
DEFINE_HAS_SIGNATURE(has_foo, T::foo, void (*)(void));
这里有一种方法:
#include <type_traits>
template<typename, typename>
struct has_fun;
template<typename T, typename Ret, typename... Args>
struct has_fun<T, Ret(Args...)> {
template<typename U, U> struct Check;
template<typename U>
static std::true_type Test(Check<Ret(*)(Args...), &U::fun>*);
template<typename U>
static std::false_type Test(...);
static const bool value = decltype(Test<T>(0))::value;
};
它是为一个名为fun
的函数编写的。像has_fun<T, int(int, int)>::value
一样使用它。
这是另一个:
#include <type_traits>
template<typename, typename>
struct has_fun;
template<typename T, typename Ret, typename... Args>
struct has_fun<T, Ret(Args...)> {
struct No {}; // need a unique type for the second overload
// so it doesn't match Ret and give a false positive
template<typename U>
static auto Test(int) -> decltype( U::fun(std::declval<Args>()...) );
template<typename U>
static No Test(...);
static const bool value =
std::is_same<decltype(Test<U>(0)), Ret>{};
};
测试函数的返回类型是否可转换为Ret
,而不是检查exatch匹配,这可能是明智的。在这种情况下,使用is_convertible
而不是is_same
,同时检查返回类型是否与No
不同(正如Yakk所指出的,有些类型几乎可以由任何东西构建)。
只需调用成员函数并在SFINAE上下文中丢弃结果。如果成功,则该方法存在。如果失败,则该方法不会。
// not needed in C++1y
template<class T,class V=void>using enable_if_t=typename enable_if<T,V>::type;
// If the other tests fail, the type T does not have a method `foo` of
// signature Sig. The class=void parameter is an implementation detail
// that in an industrial quality implementation we would hide in a helper
// template type.
template<class T,class Sig,class=void>struct has_foo:std::false_type{};
// For R(Args...), we attempt to invoke `T::foo` with (Args...), then check
// if we can assign the return value to a variable of type R.
template<class T,class R,class...Args>
struct has_foo<T,R(Args...),
enable_if_t< // std:: in C++1y
std::is_convertible<
decltype( T::foo( std::declval<Args>()... ) ),
R
>::value
&& !std::is_same<R, void>::value
>
>: std::true_type {};
// for `void` return value, we only care if the function can be invoked,
// no convertible test required:
template<class T,class...Args>
struct has_foo<T,void(Args...),
decltype( void(T::foo( std::declval<Args>()... ) ) )
>: std::true_type {};
用途:
has_foo< bar, int(int) >::value
其检查int r = T::foo( 7 )
是否是有效的表达式而不是精确的签名匹配。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 如何在C++中使用非静态成员函数作为回调函数
- (C++)为什么静态成员可以在初始化之前使用
- 类的全局对象和静态成员
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- 模板化类中静态成员的延迟初始化
- 使用静态成员声明类时遇到问题
- C++:是否可以使用非静态成员变量模板?
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 如何在复杂继承中访问静态成员变量
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- C++构造函数和静态成员
- 为什么传递非静态成员函数会导致编译错误?
- 非静态成员失败的线程调用函数
- 为什么即使存在此静态成员,也不会构造它?
- 使用C ,使用SFINAE测试静态成员的存在,返回错误的值
- 在不存在的对象上调用静态成员函数
- 是否存在阻止内置具有静态成员的技术限制
- 如何检测具有特定签名的静态成员函数的存在