它不是整个概念,而是用于确定某个类是否具有n
数据成员的方法之一。这是完整的代码;普通使用SFINAE进行成员检测。
template <typename T>
struct has_X {
struct Fallback { int X; };
struct Derived : T, Fallback {};
template <typename U, U> struct S;
template <typename C> static char (&f(S<int Fallback::*, &C::X> *))[1];
template <typename C> static char (&f(...))[2];
public:
const static bool value = sizeof(f<Derived>(0)) == 2;
};
Derived
继承Fallback
和T
的部分让我感到困惑,因为当我们执行f
的重载时,&C::X
为{{1} }。但是,不应该选择此重载,因为它不会&Derived::X
保证Derived
,因为它继承自具有该数据成员的X
?
也许我忽视了一些事情。然而,这段代码已经显示并教会了我从未知道的事情,所以也许 就是这样。我期望的是总是选择那个重载(而不是Fallback
的那个),因为...
应该总是Derived
,因为它继承自X
。但这种情况并非如此。有人可以解释一下原因吗?
答案 0 :(得分:4)
Fallback
有一个名为X
的数据成员,但如果T
还有一个名为X
的成员,则Derived会有两个,其中案例Derived::X
无法明确表达。因此,如果T
没有X
,则使用第一个重载,如果T
具有X
,则使用第二个更通用的版本。这就是为什么你可以根据返回类型的大小来区分这些情况。