我发现类似的问题和答案,如 this one .但是,正如我所尝试的那样,只有在被测试的成员直接定义在被测试的类中时,这个 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);
}
最佳答案
很遗憾,在 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";
}
不幸的是,ideone 的 gcc 版本太旧了,clang 3.0 也好不到哪儿去。
关于c++ - 是否可以检查是否为类定义了成员函数,即使成员是从未知基类继承的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11008189/