需要帮助来理解下一课的目的

时间:2015-03-27 13:59:32

标签: c++ templates

我的朋友给我发了一个有趣的任务:

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进行编译。但我无法理解它的作用。

我感兴趣的地方:

  1. 如果函数只有声明但没有定义,它如何工作?
  2. TestT<T>::template test<T>(0)是什么?它看起来像一个函数调用。
  3. 这是::template的含义是什么?
  4. 上面课程的目的是什么?
  5. 如何使用原则?
  6. int C::*是指向int成员的指针,对吧?

2 个答案:

答案 0 :(得分:3)

  1. 它实际上并不调用函数,它只是查看返回类型的sizeof是什么。
  2. 是一个函数调用。见下文。
  3. 由于dependent type问题,template是必要的。
  4. 它测试是否可以指向type参数的数据成员。这仅适用于类类型(例如std::string但不适用于int)。您可以在is_class的名称下找到类似for example here的代码,其中包含与您的示例非常相似的内容。
  5. SFINAE,代表“替换失败不是错误”。一旦您意识到C替换int将失败并因此导致其中一个函数重载不存在(而不是导致编译器错误并中止编译),这个名称的原因就变得很明显了
  6. 是的,它是一个指针,指向int类型对象内的C

答案 1 :(得分:1)

对于单个问题,这个问题太多了,但不过:

  1. sizeof不评估其操作数,它只确定类型。这不需要操作数调用的任何函数的定义 - 类型由声明确定。

  2. 是的,这是一个函数调用。如果类和函数不是模板,它看起来像TestT::test(0)

  3. template是必需的,因为名称test的含义取决于类模板参数,如Where and why do I have to put the "template" and "typename" keywords?中所述。

  4. 它定义了一个常量Yes,如果T是类类型则为1,否则为零。也是具有逻辑反转值的常量No

  5. 看起来它打算在SFINAE中使用,以允许模板部分专门用于类和非类类型。从C ++ 11开始,我们可以使用std::is_class等标准特征来实现此目的。

  6. 是的,如果C是类类型。否则,它是一个类型错误,因此忽略了采用该类型的重载,只留下第二个重载。因此,如果test是类类型,则ONE的返回类型为C(大小为1),否则为TWO(大小为2);所以sizeof(...) == 1的测试区分了类和非类类型。