2013-03-06 136 views
1

我很难理解为什么在以下两段代码中存在差异,编译器究竟在做什么。从模板基类派生类型时未找到

我的琐碎以下代码位,符合市场预期,没有任何问题,编译:

class base 
{ 
public: 
    typedef int booboo; 
}; 

class derived : public base 
{ 
public: 
    int boo() 
    { 
     booboo bb = 1; 
     return bb; 
    } 
}; 

int main() 
{ 
    derived d; 
    d.boo(); 
    return 0; 
} 

我把代码从上面添加一些模板参数,并开始得到错误与类型BOOBOO不为有效:

template <typename T> 
class base 
{ 
public: 
    typedef T booboo; 
}; 

template <typename T> 
class derived : public base<T> 
{ 
public: 
    //typedef typename base<T>::booboo booboo; <-- fixes the problem 
    booboo boo() 
    { 
     booboo bb = T(1); 
     return bb; 
    } 
}; 

int main() 
{ 
    derived<int> d; 
    d.boo(); 
    return 0; 
} 

错误:

prog.cpp:13:4: error: ‘booboo’ does not name a type 
prog.cpp:13:4: note: (perhaps ‘typename base<T>::booboo’ was intended) 
prog.cpp: In function ‘int main()’: 
prog.cpp:23:6: error: ‘class derived<int>’ has no member named ‘boo’ 

http://ideone.com/jGKYIC

我想详细了解一个典型的C++编译器如何编译代码的模板版本,它与编译原始示例有什么不同,这是一个需要多次代码传递的问题,类型依赖查找?

+0

发布您的问题中包含的错误总是值得的。 – JBentley 2013-03-06 00:40:57

+0

@JBentley:对不起,现在我会更新这个问题。 – 2013-03-06 00:43:20

回答

2

在第二个版本中,booboo是一个从属名称,所以它不会在模板中自动显示。您可以将using typename base<T>::booboo;添加到派生类,或使用您的typedef解决方案,或者说typename base<T>::booboo bb = T(1);

+2

只是为了澄清,实质上这意味着一开始编译器不能保证没有基类模板的特殊化,而忽略了'booboo'的定义,或者可能将'booboo'定义为函数或其他。因此必须告诉编译器关于名称的假设:它来自基类,并且它是一种类型。 – 2013-03-06 00:47:43

+0

@Kerrek:你会碰巧知道标准中描述/谈论类型在处理模板时可见的部分吗?还是它是一个实现定义的问题? – 2013-03-06 00:51:00

+0

@SamiKenjat:在C++ 11中,它是14.6.2,“从属名称”。基本上,如果左边是一个模板专门化,则在'::'右边的任何名称。 – 2013-03-06 01:02:09