che*_*kow 43 c++ templates c++-faq derived-class
考虑:
template <typename T>
class Base
{
public:
static const bool ZEROFILL = true;
static const bool NO_ZEROFILL = false;
}
template <typename T>
class Derived : public Base<T>
{
public:
Derived( bool initZero = NO_ZEROFILL ); // NO_ZEROFILL is not visible
~Derived();
}
Run Code Online (Sandbox Code Playgroud)
我无法用GCC g ++ 3.4.4(cygwin)编译它.
在将这些转换为类模板之前,它们是非泛型的,派生类能够看到基类的静态成员.在C++规范的要求中是否会失去可见性,还是需要使用语法更改?
据我了解,每个实例Base<T>都会有它自己的静态成员" ZEROFILL"和" NO_ZEROFILL",这Base<float>::ZEROFILL和Base<double>::ZEROFILL是不同的变量,但我真的不关心; 常量是为了代码的可读性.我想使用静态常量,因为在名称冲突而不是宏或全局方面更安全.
sbi*_*sbi 46
那是你的两阶段查找.
Base<T>::NO_ZEROFILL(所有大写标识符都是boo,除了宏,BTW)是依赖的标识符T.
因为,当编译器首先解析模板时,T尚未替换实际类型,编译器不"知道"是什么Base<T>.因此,它不能知道您假设在其中定义的任何标识符(T编译器稍后可能会看到某些特殊化),并且您不能忽略基类中定义的标识符的基类限定.
这就是你必须写Base<T>::NO_ZEROFILL(或this->NO_ZEROFILL)的原因.这告诉编译器这NO_ZEROFILL是基类中的某个东西,它依赖于T它,并且只有在实例化模板时它才能验证它.因此,它将接受它而不试图验证代码.
只有在通过提供实际参数来实例化模板时,才能在以后验证该代码T.
Ric*_*den 29
您遇到的问题是由于依赖基类的名称查找规则.14.6/8有:
在查找模板定义中使用的名称声明时,通常的查找规则(3.4.1,3.4.2)用于非依赖名称.依赖于模板参数的名称查找被推迟,直到知道实际模板参数(14.6.2).
(这不是真正的"两阶段查找" - 请参阅下面的解释.)
关于14.6/8的观点是,就NO_ZEROFILL您的示例中的编译器而言,它是一个标识符,并且不依赖于模板参数.因此,它按照3.4.1和3.4.2中的正常规则进行查找.
此正常查找不会在内部搜索Base<T>,因此NO_ZEROFILL只是一个未声明的标识符.14.6.2/3有:
在类模板的定义或类模板的成员中,如果类模板的基类依赖于模板参数,则在类的定义时,在非限定名称查找期间不会检查基类作用域.模板或成员或在类模板或成员的实例化期间.
当你有资格NO_ZEROFILL跟Base<T>::在本质上,你是从一个非从属名称为依赖一个改变它,当你做,你耽误了查找,直到模板实例.
附注:什么是两阶段查找:
void bar (int);
template <typename T>
void foo (T const & t) {
bar (t);
}
namespace NS
{
struct A {};
void bar (A const &);
}
int main ()
{
NS::A a;
foo (a);
}
Run Code Online (Sandbox Code Playgroud)
上面的例子编译如下.编译器解析函数体foo并查看是否存在bar具有依赖参数的调用(即,依赖于模板参数的参数).此时,编译器按3.4.1查找栏,这是"阶段1查找".查找将找到该函数,void bar (int)并与依赖调用一起存储,直到稍后.
然后,当模板被实例化时(作为调用的结果main),编译器然后在参数的范围内执行额外的查找,这是"阶段2查找".这种情况导致发现void NS::bar(A const &).
编译器有两个重载bar,它在它们之间进行选择,在上面的情况下调用void NS::bar(A const &).
| 归档时间: |
|
| 查看次数: |
16442 次 |
| 最近记录: |