为什么实例化对于局部变量而不是静态?

时间:2016-11-02 10:03:02

标签: c++ templates compiler-errors

我正在尝试找到一种简单的方法(使用预C ++ 11,即没有decltype)来记录模板对类型的要求,以便正常工作。也许有更好的方法来做到这一点。但是,这是我的问题:

#include <iostream>

template <typename T> struct Foo {
    static const int test = sizeof(T::size);
};

template <typename T> struct DetectAndError {
    DetectAndError() { int test = sizeof(T::size); }
};

struct Bar {};

int main() {
    Foo<Bar> x;                            // NO ERROR ? :/
    // std::cout << x.test << std::endl;   // ERROR :)
    // DetectAndError<Bar> y;              // ERROR :)
}

为什么Foo<Bar> x;不是错误? 对于其他线路,我得到了我想要的东西:

error: 'size' is not a member of 'Bar' 

2 个答案:

答案 0 :(得分:8)

这是因为标准要求test仅在使用时才会被实例化。模板类的成员变量/成员函数/静态成员在没有使用它们的情况下不会被实例化。

在您的情况下,当您尝试执行x.test编译器时,会尝试查找test,然后无法执行此操作,因为x::size丢失了。

根据标准,这种行为几乎被接受,并且是普遍的。

答案 1 :(得分:5)

另一个答案是有效的,但这里有一些支持:

  

N4140§14.7.1[temp.inst] / 1和2

     

类模板特化的隐式实例化导致   声明的隐式实例化,但不是   定义,默认参数或异常规范的   类成员函数,成员类,作用域成员枚举,   静态数据成员和成员模板;它导致了隐含的   实例化未作用域成员枚举的定义   成员匿名工会。

     

成员的特化是在隐式实例化的时候   在需要成员的上下文中引用特化   定义存在;特别是初始化(和任何   除非发生静态数据成员的相关副作用   静态数据成员本身以需要的方式使用   要存在的静态数据成员的定义。

因此,test仅在第一行中声明,但在尝试实例化时会产生错误。至于DetectAndError,你隐式调用它的默认构造函数。 typedef DetectAndError<Foo> fooDetectAndError<Foo>* ptr应该编译没有任何问题