c++ - 为什么这个模板代码可以编译?

标签 c++ templates

我正在处理一个大型项目,其中包含一段可以编译的代码 - 但我不明白如何编译。我将其提炼为这个简单的示例:

template <typename T>
struct First {
    typedef int type;           // (A)
    typename T::Three order;    // (B)
};

template <typename T> struct Second {
    typedef typename T::type type;
};


template <typename T> struct Third {
    int val;
    T two;
};

struct Traits {
    typedef First<Traits> One;
    typedef Second<One> Two;
    typedef Third<Two> Three;
};

int main(int argc, char** argv) {
    Traits::One x;
};

类(class)FirstTraits 为模板和引用文献 Traits::Three ,它本身就是一个 typedef基于 Two ,这是一个 typedef基于 First<Traits> ...因此它是循环的。但是这段代码在 gcc4.6 和 VC10 上都编译得很好。但是,如果我翻转标记为 (A) 的两行的顺序和 (B) ,代码无法编译,提示 typedef Second 内部.

为什么这段代码可以编译,为什么 typedef 的顺序是这样的?成员变量很重要吗?

最佳答案

有几件事值得一提。

  • 如果 Second,代码将中断被修改为包含

    T badObject;
    

    有一个很长的“实例化自...”链并以“不完整类型”错误结尾,这是由于您期望的循环性,但如果您改为添加则不会

    typename T::type object;
    

    这是在告诉你编译器在巧妙地观察它不需要完全封装T ,才知道是什么T::type是。为了说明这一点,请注意您可以合法拥有

    First { ... typedef T type; ... }
    Second { typename T::type object; }
    

    因为 T 不包含当前定义的对象,或者

    First { ... typedef typename T::One type; ... }
    Second { typedef typename T::type object; }
    

    typedefSecond也不需要任何对象的实例 - 但不需要,比如说,

    First { ... typedef typename T::One type; ... }
    Second { typename T::type object; }
    

    因为只有这样,编译器才真正需要嵌套 First<Traits> First<Traits> 中的对象对象。

  • 交换 (A) 和 (B) 的问题在于,编译器在上面采用的巧妙技巧是通过引入每个专用模板定义的新拷贝来工作的,一次解析它的一行时间。如果它没有达到 First 中的类型定义,就会发生错误当需要通过 Second 了解它时.

关于c++ - 为什么这个模板代码可以编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15935461/

相关文章:

c++ - C/C++ PCM开源音频分析仪

c++ - 以具有复数元素和下三角方阵 A 矩阵的线性最小二乘法求解系统 Ax=b

c++ - 在模板类 (C++) 中创建 boost.bimap 时的警告

c++ - 自定义Vector类,像c++中的数组一样返回 vector

c++ - CMAKE MAC OSX 库链接问题 : compiles on Linux but on on Mac

c++ - Clion,在 C++ 项目中创建新文件

c++ - 在 VS2015 中键入 SFINAE 编译,但生成错误

用于删除和重置指针的 C++ 模板函数

c++ - 检查类型是否是模板的实例化

c++ - 使用 clang 编译 MSVC 标准库。类范围内的显式模板函数特化