C++ 关于成员检测代码的说明
它不是作为一个整体的概念,而是它用来确定类是否有C++ 关于成员检测代码的说明,c++,C++,它不是作为一个整体的概念,而是它用来确定类是否有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>
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;
};
模板
结构具有{
结构回退{int X;};
派生结构:T,回退{};
模板结构;
模板静态字符&f(S*)[1];
模板静态字符(&f(…)[2];
公众:
常量静态布尔值=sizeof(f(0))==2;
};
Derived
继承自Fallback
和T
的部分让我感到困惑,因为当我们执行f
的重载时,&C::X
是&Derived::X
。但是这个重载不应该总是被选择,因为派生的不是保证有X
,因为它继承了具有该数据成员的回退
也许我忽略了什么。然而,这段代码向我展示并教会了我一些我不知道的东西,所以也许这其中有一些东西。我希望总是选择该重载(而不是带有..
的重载),因为派生的应该始终具有X
,因为它继承自回退
。但事实并非如此。有人能解释一下原因吗?Fallback
有一个名为X
的数据成员,但是如果T
也有一个名为X
的成员,则派生将有两个,在这种情况下,不能明确地采用派生::X
。因此,如果T
没有X
,则使用第一个重载,如果T
有X
,则使用第二个更通用的版本。这就是为什么你可以根据返回类型的大小来区分这些情况。你是说S
?@NateKohl是的,很抱歉我是从内存中写的……顺便说一句,看起来你颠倒了逻辑(value
将true
如果T
没有X
)。与1比较或切换f
的返回类型。@AndersJohansson感谢您指出这一点。我的错误你的意思不是含糊不清吗?@David,不是-如果t
有一个名为X
的成员,那么派生的::X
就不能被明确地接受,即派生的::X
是含糊不清的。对于双重否定表示抱歉;)好的,顺便说一句,回答得很好。:)