在一段代码中,我发现了一些东西:
template<typename T>
class IsClassT {
private:
typedef char One;
template<typename C> static One test(int C::*);
...
Run Code Online (Sandbox Code Playgroud)
问题是我在哪里可以找到关于为什么"int C ::*"的使用在函数test()定义中有效的描述?
CB *_*ley 10
int C::*是指向C类型成员的指针int.搜索"指向成员的指针".处理此声明语法的标准部分(ISO/IEC 14882:2003)是8.3.3指向成员的指针[dcl.mptr].
用法示例.
struct Example
{
int a;
int b;
};
int test( Example& ex, int Example::* p )
{
return ex.*p;
}
int main()
{
Example x = { 3, 5 };
// Convoluted way of extracting x.a and x.b
int a = test( x, &Example::a );
int b = test( x, &Example::b );
}
Run Code Online (Sandbox Code Playgroud)
我不会描述是什么int C::*意思,因为@Charles Bailey已经做得非常好.不过我会回答你的问题:
(...)为什么"int C ::*"的使用在函数test()定义中有效?
关键点是,当且仅当是类类型时,int C::*(指向类型成员的指针int)的使用是有效的.否则该类型是不正确的. Cint C::*
这就是你的原因
template<typename C> static One test(int C::*);
Run Code Online (Sandbox Code Playgroud)
而且很可能在下面的某个地方
template <typename> static Two test(...);
static const bool value = sizeof(test<T>(0)) == 1;
Run Code Online (Sandbox Code Playgroud)
当test<T>(0)编译器看到它时,它会检查候选者test.它找到两个:
template<typename C> static One test(int C::*);
template <typename> static Two test(...);
Run Code Online (Sandbox Code Playgroud)
第一个优先于第二个,因为1)它们都是模板函数,2)最后查找省略号.如果第一个形成不良(即,当且仅当 C不是类类型)时,则简单地丢弃它并且进行第二次重载.此行为的昵称为SFINAE(替换失败不是错误).
测试返回类型的大小(记住sizeof(char)始终为1),您可以在编译时评估test,即.是否T是类类型.