我正在尝试找到一种简单的方法(使用预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'
答案 0 :(得分:8)
这是因为标准要求test
仅在使用时才会被实例化。模板类的成员变量/成员函数/静态成员在没有使用它们的情况下不会被实例化。
在您的情况下,当您尝试执行x.test
编译器时,会尝试查找test
,然后无法执行此操作,因为x::size
丢失了。
根据标准,这种行为几乎被接受,并且是普遍的。
答案 1 :(得分:5)
另一个答案是有效的,但这里有一些支持:
N4140§14.7.1[temp.inst] / 1和2
类模板特化的隐式实例化导致 声明的隐式实例化,但不是 定义,默认参数或异常规范的 类成员函数,成员类,作用域成员枚举, 静态数据成员和成员模板;它导致了隐含的 实例化未作用域成员枚举的定义 成员匿名工会。
成员的特化是在隐式实例化的时候 在需要成员的上下文中引用特化 定义存在;特别是初始化(和任何 除非发生静态数据成员的相关副作用 静态数据成员本身以需要的方式使用 要存在的静态数据成员的定义。
因此,test
仅在第一行中声明,但在尝试实例化时会产生错误。至于DetectAndError
,你隐式调用它的默认构造函数。 typedef DetectAndError<Foo> foo
或DetectAndError<Foo>* ptr
应该编译没有任何问题