【发布时间】:2019-06-02 05:52:02
【问题描述】:
第一次发帖,希望不要违反任何礼仪。随时提出建议以使问题变得更好。
我看过一些与此类似的帖子:Check if a class has a member function of a given signature,但没有一个完全符合我的要求。当然,它“适用于多态性”,因为它可以正确检查来自超类的函数的子类类型,但我想做的是检查对象本身而不是类。使用该帖子中的一些(略微调整的)代码:
// 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();
}
显然这是无效的语法,但希望它能够理解这一点。
【问题讨论】:
-
很不清楚你的意思是什么:“但我想做的是检查对象本身而不是类。”一个对象具有其类的属性,那么有什么区别?
-
@Klaus - 如果我正确理解 OP 的意思,他有一个派生类型的对象并将其作为基类型的指针传递。他想知道是否有可能从指向基类型的指针中检测到原始对象是否具有具有特定名称和签名的方法。
-
是的,@max66 是正确的。我不太清楚底层组织是如何工作的,但我最初的想法是该对象必须携带某种函数查找表来解析虚拟和继承的函数调用,并且您应该能够进入该函数表以查看如果一个特定的存在。但是,实际上 c++ 对象似乎不携带这些信息,所以可用的函数完全取决于您将其视为的类型
标签: c++11 templates c++14 c++17 sfinae