这个 has_member 类模板如何工作?
我试图了解以下类模板的工作原理(取自 此处),但我无法正确理解它:
template <typename Type>
class has_member
{
class yes { char m;};
class no { yes m[2];};
struct BaseMixin
{
void operator()(){}
};
struct Base : public Type, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U>
static no deduce(U*, Helper<void (BaseMixin::*)(), &U::operator()>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
更具体地说,我不明白 BaseMixin
的目的以及其中的operator()
。另外,由于 Base
是从它派生的,所以我也不理解它。
更具体地说,当模板参数Type
定义了operator()
时,为什么只有才会触发SFINAE,导致第一个deduce( )
函数被忽略并选择第二个函数?
无论如何,这是我的测试代码:
struct A{}; //SFINAE is triggered for A
struct B{ void operator()(){} }; //SFINAE is not triggered for B
struct C{ void operator()(int,int){} }; //SFINAE is not triggered for C
int main()
{
std::cout << std::boolalpha; //enable true/false instead of 1/0!
std::cout << has_member<A>::result << std::endl;
std::cout << has_member<B>::result << std::endl;
std::cout << has_member<C>::result << std::endl;
}
输出(ideone):
false
true
true
I'm trying to understand how the following class template works (taken from here), but I couldn't understand it properly:
template <typename Type>
class has_member
{
class yes { char m;};
class no { yes m[2];};
struct BaseMixin
{
void operator()(){}
};
struct Base : public Type, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U>
static no deduce(U*, Helper<void (BaseMixin::*)(), &U::operator()>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
More specifically, I don't understand the purpose of BaseMixin
and the presence of operator()
in it. Also, since Base
is derived from it, I don't understand it as well.
Even more specifically, when template parameter Type
has defined operator()
, why only then SFINAE is triggered, causing the first deduce()
function to be ignored and the second one is chosen?
Anyway, this is my test code:
struct A{}; //SFINAE is triggered for A
struct B{ void operator()(){} }; //SFINAE is not triggered for B
struct C{ void operator()(int,int){} }; //SFINAE is not triggered for C
int main()
{
std::cout << std::boolalpha; //enable true/false instead of 1/0!
std::cout << has_member<A>::result << std::endl;
std::cout << has_member<B>::result << std::endl;
std::cout << has_member<C>::result << std::endl;
}
Output(ideone):
false
true
true
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
BaseMixin
有一个operator()
定义。Base
派生自Type
和BaseMixin
,因此如果Type
有一个operator()
那么Base::operator()
上的名称查找将是不明确的。deduce
是针对Base*
而不是Type*
调用的。Helper
仅当&U::operator()
明确解析时才会实例化到BaseMixin::operator()
。Helper
没有实例化,这是因为Type< /code> 有自己的
operator()
,使得&U::operator()
上的名称查找不明确,因此导致deduce
的重载返回选择类型yes
。关于第二个项目符号的标准引用 - C++11 §10.2/2-6:
BaseMixin
has anoperator()
definition.Base
derives from bothType
andBaseMixin
, so ifType
has anoperator()
then name lookup onBase::operator()
will be ambiguous.deduce
is called forBase*
, notType*
.Helper<void (BaseMixin::*)(), &U::operator()>
will only instantiate if&U::operator()
unambiguously resolves toBaseMixin::operator()
.Helper<void (BaseMixin::*)(), &U::operator()>
does not instantiate, it's becauseType
has its ownoperator()
making name lookup on&U::operator()
ambiguous, and consequently the overload ofdeduce
returning typeyes
is chosen.Standard citation regarding the second bullet — C++11 §10.2/2-6:
Base
可以从Type
继承operator()
,或者从BaseMixin
继承,如果Type
有operator()
它隐藏了BaseMixin
的运算符。因此,如果* = 0) code> 将匹配。
Type
没有定义operator ()
,则Base
的operator()
可以隐式转换为BaseMixin
的operator()
。然后,用U==Base
推导(U*, Helper相反,如果
Type
定义了operator()
,则Base
的operator()
无法转换为BaseMixin
是其中之一,因此derive(U*, Helper* = 0)
将不匹配。Base
can inheritoperator()
fromType
, or fromBaseMixin
and ifType
hasoperator()
it hidesBaseMixin
's operator.So, if
Type
has nooperator ()
defined,Base
'soperator()
can be casted implicitly toBaseMixin
'soperator()
. Then,deduce(U*, Helper<void (BaseMixin::*)(), &U::operator()>* = 0)
withU==Base
will match.Oppositely, if
Type
hasoperator()
defined,Base
'soperator()
cannot be casted toBaseMixin
's one, sodeduce(U*, Helper<void (BaseMixin::*)(), &U::operator()>* = 0)
will not match.