C++ 检查泛型对象是否具有匹配签名的成员函数
C++ Check if generic object has member function matching signature
首先post,所以希望不要违反任何礼节。随时提出改进问题的建议。
我见过一些与此类似的 post:Check if a class has a member function of a given signature,但 none 完全符合我的要求。当然它 "works with polymorphism" 在某种意义上它可以正确检查来自 superclass 的函数的 subclass 类型,但我想做的是检查对象本身和不是 class。使用 post:
中的一些(稍微调整过的)代码
// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
static_assert(integral_constant<T, false>::value,
"Second template parameter needs to be of function type."
);
};
template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {
template<typename T>
static constexpr auto check(T*) -> typename is_same<
decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;
template<typename>
static constexpr false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};
我想要如下内容:
// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
if (HasFunction<T, int(double)>::value)
cout << "Found it!" << endl;
// Do something with obj.myfunc
else cout << "Nothin to see here" << endl;
}
int main()
{
Y y;
W* w = &y; // same object
DoSomething(y); // Found it!
DoSomething(*w); // Nothin to see here?
}
问题在于以多态方式查看同一对象会导致不同的结果(因为推导的类型是正在检查的对象而不是对象)。因此,例如,如果我正在迭代 W* 的集合并调用 DoSomething,我希望它对 W 不执行任何操作,但它应该为 X 和 Y 做一些事情。这是可以实现的吗?我仍在研究模板,所以我仍然不太确定什么是可能的,但似乎不是。有完全不同的方法吗?
此外,与该特定问题的相关性略低:有没有办法让 HasFunction 更像一个接口,这样我就可以任意检查不同的函数?即里面没有具体的“.myfunc”? (好像只有用宏才有可能?)例如
template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
Bar b;
if(HasFoo<b>::value) b.foo();
}
显然这是无效的语法,但希望它能说明问题。
无法对基 class 指针执行深度检查以检查 pointed-to 类型上可能的成员函数(对于提前未知的派生类型) .即使我们得到反射。
C++ 标准没有提供给我们进行这种检查的方法,因为保证可用的 运行 时间类型信息非常有限,基本上属于 type_info结构。
您的 compiler/platform 可能会提供额外的 run-time 类型信息,您可以挂钩这些信息,尽管用于提供 RTTI 的确切类型和机制通常没有记录且难以检查 (This article由 Quarkslab 尝试检查 MSVC 的 RTTI 层次结构)
首先post,所以希望不要违反任何礼节。随时提出改进问题的建议。
我见过一些与此类似的 post:Check if a class has a member function of a given signature,但 none 完全符合我的要求。当然它 "works with polymorphism" 在某种意义上它可以正确检查来自 superclass 的函数的 subclass 类型,但我想做的是检查对象本身和不是 class。使用 post:
中的一些(稍微调整过的)代码// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
static_assert(integral_constant<T, false>::value,
"Second template parameter needs to be of function type."
);
};
template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {
template<typename T>
static constexpr auto check(T*) -> typename is_same<
decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;
template<typename>
static constexpr false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};
我想要如下内容:
// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
if (HasFunction<T, int(double)>::value)
cout << "Found it!" << endl;
// Do something with obj.myfunc
else cout << "Nothin to see here" << endl;
}
int main()
{
Y y;
W* w = &y; // same object
DoSomething(y); // Found it!
DoSomething(*w); // Nothin to see here?
}
问题在于以多态方式查看同一对象会导致不同的结果(因为推导的类型是正在检查的对象而不是对象)。因此,例如,如果我正在迭代 W* 的集合并调用 DoSomething,我希望它对 W 不执行任何操作,但它应该为 X 和 Y 做一些事情。这是可以实现的吗?我仍在研究模板,所以我仍然不太确定什么是可能的,但似乎不是。有完全不同的方法吗?
此外,与该特定问题的相关性略低:有没有办法让 HasFunction 更像一个接口,这样我就可以任意检查不同的函数?即里面没有具体的“.myfunc”? (好像只有用宏才有可能?)例如
template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
Bar b;
if(HasFoo<b>::value) b.foo();
}
显然这是无效的语法,但希望它能说明问题。
无法对基 class 指针执行深度检查以检查 pointed-to 类型上可能的成员函数(对于提前未知的派生类型) .即使我们得到反射。
C++ 标准没有提供给我们进行这种检查的方法,因为保证可用的 运行 时间类型信息非常有限,基本上属于 type_info结构。
您的 compiler/platform 可能会提供额外的 run-time 类型信息,您可以挂钩这些信息,尽管用于提供 RTTI 的确切类型和机制通常没有记录且难以检查 (This article由 Quarkslab 尝试检查 MSVC 的 RTTI 层次结构)