我的朋友给我发了一个有趣的任务:
template<typename T>
class TestT
{
public:
typedef char ONE;
typedef struct { char a[2]; } TWO;
template<typename C>
static ONE test(int C::*);
template<typename C>
static TWO test(...);
public:
enum{ Yes = sizeof(TestT<T>::template test<T>(0)) == 1 };
enum{ No = !Yes };
};
我无法使用VS2013编译此代码。使用GCC 4.9.0进行编译。但我无法理解它的作用。
我感兴趣的地方:
TestT<T>::template test<T>(0)
是什么?它看起来像一个函数调用。::template
的含义是什么?int C::*
是指向int
成员的指针,对吧?答案 0 :(得分:3)
sizeof
是什么。template
是必要的。std::string
但不适用于int
)。您可以在is_class
的名称下找到类似for example here的代码,其中包含与您的示例非常相似的内容。C
替换int
将失败并因此导致其中一个函数重载不存在(而不是导致编译器错误并中止编译),这个名称的原因就变得很明显了int
类型对象内的C
。答案 1 :(得分:1)
对于单个问题,这个问题太多了,但不过:
sizeof
不评估其操作数,它只确定类型。这不需要操作数调用的任何函数的定义 - 类型由声明确定。
是的,这是一个函数调用。如果类和函数不是模板,它看起来像TestT::test(0)
。
template
是必需的,因为名称test
的含义取决于类模板参数,如Where and why do I have to put the "template" and "typename" keywords?中所述。
它定义了一个常量Yes
,如果T
是类类型则为1,否则为零。也是具有逻辑反转值的常量No
。
看起来它打算在SFINAE中使用,以允许模板部分专门用于类和非类类型。从C ++ 11开始,我们可以使用std::is_class
等标准特征来实现此目的。
是的,如果C
是类类型。否则,它是一个类型错误,因此忽略了采用该类型的重载,只留下第二个重载。因此,如果test
是类类型,则ONE
的返回类型为C
(大小为1),否则为TWO
(大小为2);所以sizeof(...) == 1
的测试区分了类和非类类型。