C ++检查泛型对象是否具有与签名匹配的成员函数

时间:2019-06-02 05:52:02

标签: c++11 templates c++14 c++17 sfinae

第一篇文章,所以希望不要违反任何礼节。随时提出改进问题的建议。

我看过几则与此类似的文章: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();
}

很明显,这是无效的语法,但希望可以理解这一点。

1 个答案:

答案 0 :(得分:0)

为了检查指向类型(对于事先未知的派生类型)可能的成员函数,根本不可能对基类指针执行深度检查。即使我们得到反思。

C ++标准无法为我们提供这种检查的方法,因为可以保证可用的运行时类型信息的类型非常有限,基本上只能归为type_info结构。

您的编译器/平台可能会提供附加的运行时类型信息,尽管用于提供RTTI的确切类型和机制通常没有记录且难以检查(Quarkslab尝试This article来检查MSVC的信息)。 RTTI层次结构)