是否可以检查是否为类定义了成员函数,即使该成员是从未知的基类继承的

Yan*_*hou 5 c++ sfinae

我发现类似的问题和答案像这一个.但是,正如我尝试的那样,如果测试成员直接在被测试的类中定义,则此SFINAE测试仅成功.例如以下,类B,D1打印HAS而另外两个打印NOT HAS.有没有一种方法来确定,如果一个类有一个成员,无论是由自己定义,或基类和基类的名称没有在这种情况下,已知的.我的动机是,我想编写一个泛型函数,如果它存在,将调用某个方法(从基础或不基础,参数的类型是通用的,留下其可能的基类型).

#include <iostream>

class HasFoo
{
    public :

    typedef char Small;
    typedef struct {char; char;} Large;

    template <typename C, void (C::*) ()> class SFINAE {};

    template <typename C> static Small test (SFINAE<C, &C::foo> *)
    {
        std::cout << "HAS" << std::endl;
    }

    template <typename C> static Large test (...)
    {
        std::cout << "NOT HAS" << std::endl;
    }
};

class B
{
    public :

    void foo () {}
};

class D1 : public B
{
    public :

    void foo () {} // overide
};

class D2 : public B
{
    public :

    using B::foo;
};

class D3 : public B {};

int main ()
{
    HasFoo::test<B>(0);
    HasFoo::test<D1>(0);
    HasFoo::test<D2>(0);
    HasFoo::test<D3>(0);
}
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 8

在C++ 03中,遗憾的是这不可能,抱歉.

在C++ 11中,由于其神奇之处,事情变得更加容易decltype.decltype允许您编写表达式来推断其结果的类型,因此您可以完美地命名基类的成员.如果方法是模板,则SFINAE适用于decltype表达式.

#include <iostream>

template <typename T>
auto has_foo(T& t) -> decltype(t.foo(), bool()) { return true; }

bool has_foo(...) { return false; }


struct Base {
    void foo() {}
};

struct Derived1: Base {
    void foo() {}
};

struct Derived2: Base {
    using Base::foo;
};

struct Derived3: Base {
};

int main() {
    Base b; Derived1 d1; Derived2 d2; Derived3 d3;

    std::cout << has_foo(b) << " "
              << has_foo(d1) << " "
              << has_foo(d2) << " "
              << has_foo(d3) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,ideone有一个版本的gcc,这个版本太旧了,而clang 3.0并不是更好.


iam*_*ind 5

不幸的是,至少在 C++03 中这是不可能的,我也怀疑在 C++11 中。

几个重要的点:

  1. 提议的 SFINAE 仅在该方法是 public
  2. 即使 SFINAE 适用于基本方法,第 (1) 点也适用;因为对于privateprotected继承 SFINAE 可能最终无用
  3. 假设您可能只想处理public方法/继承,HasFoo::test<>可以增强代码以获取多个参数,其中也可以传递基类; std::is_base_of<>可用于进一步验证基础/派生关系;然后也对基类应用相同的逻辑