猿问

SFINAE检查继承的成员函数

使用SFINAE,我可以检测给定类是否具有某些成员函数。但是,如果我想测试继承的成员函数怎么办?


以下内容在VC8和GCC4中不起作用(即检测到A具有成员函数foo(),但不能B继承成员函数):


#include <iostream>


template<typename T, typename Sig>                                 

struct has_foo {                     

    template <typename U, U> struct type_check;

    template <typename V> static char (& chk(type_check<Sig, &V::foo>*))[1];

    template <typename  > static char (& chk(...))[2]; 

    static bool const value = (sizeof(chk<T>(0)) == 1);

};


struct A {

    void foo();

};


struct B : A {};


int main()

{

    using namespace std;

    cout << boolalpha << has_foo<A, void (A::*)()>::value << endl; // true

    cout << boolalpha << has_foo<B, void (B::*)()>::value << endl; // false

}

那么,有没有办法测试继承的成员函数?


慕的地10843
浏览 534回答 3
3回答

蛊毒传说

joshperry的回答非常聪明和优雅,但是(如后文所述)它不能正确检查foo()的签名,并且不能与基本类型(如int)一起使用:这会导致编译器错误。我将提出一种可以正确处理继承的成员并检查成员函数签名的技术。我将不做详细介绍,而是给您两个示例,并希望代码能说明一切。范例1:我们正在检查具有以下签名的成员:&nbsp; T::const_iterator begin() consttemplate<class T> struct has_const_begin{&nbsp; &nbsp; typedef char (&Yes)[1];&nbsp; &nbsp; typedef char (&No)[2];&nbsp; &nbsp; template<class U>&nbsp;&nbsp; &nbsp; static Yes test(U const * data,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typename std::enable_if<std::is_same<&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;typename U::const_iterator,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;decltype(data->begin())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >::value>::type * = 0);&nbsp; &nbsp; static No test(...);&nbsp; &nbsp; static const bool value = sizeof(Yes) == sizeof(has_const_begin::test((typename std::remove_reference<T>::type*)0));};请注意,它甚至检查方法的一致性,并且也适用于原始类型。(我的意思has_const_begin<int>::value是假的,不会引起编译时错误。)例子2现在我们正在寻找签名: void foo(MyClass&, unsigned)template<class T> struct has_foo{&nbsp; &nbsp; typedef char (&Yes)[1];&nbsp; &nbsp; typedef char (&No)[2];&nbsp; &nbsp; template<class U>&nbsp; &nbsp; static Yes test(U * data, MyClass* arg1 = 0,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typename std::enable_if<std::is_void<&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;decltype(data->foo(*arg1, 1u))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >::value>::type * = 0);&nbsp; &nbsp; static No test(...);&nbsp; &nbsp; static const bool value = sizeof(Yes) == sizeof(has_foo::test((typename std::remove_reference<T>::type*)0));};请注意,MyClass不一定是默认可构造的,也不必满足任何特殊概念。该技术也适用于模板成员。我热切地等待对此的意见。
随时随地看视频慕课网APP
我要回答