我有一个这样的课程
template< typename T >
class vector {
public:
typedef T & reference;
typedef T const & const_reference;
typedef size_t size_type;
const_reference at( size_t ) const;
reference at( size_t );
以后在同一个文件中
template< typename T >
typename vector<T>::const_reference // Line X
vector<T>::at( size_type i ) const
{
rangecheck();
return elems_[ i ];
}
template< typename T >
reference // Line Y
vector<T>::at( size_type i )
{
rangecheck();
return elems_[ i ];
}
X行编译正常,但Y行无法编译。来自g ++(版本4.4.1)的错误消息是:
foo.h:Y: error: expected initializer before 'vector'
由此我得知,如果我想要非内联函数,那么我必须完全限定typedef名称,如第X行所示。(注意,size_type
没有问题。)
然而,至少在我看来,X线看起来很笨拙。
有替代方法吗?
答案 0 :(得分:4)
是的,在类外成员函数定义中,您必须为嵌套返回类型使用完全限定名称。这个BTW与模板无关。这也是非模板类的方式。
在您的情况下,它是一个模板类,因此,由于您使用限定名称来引用依赖模板类中的嵌套类型,因此必须在其前面添加关键字typename
但是,您只需要限定返回类型。参数类型不需要限定
template< typename T >
typename vector<T>::const_reference
vector<T>::some_method( const_reference r ) const
{
// ...
}
您也可以选择为参数类型使用限定名称,但在这种情况下,您必须执行与返回类型相同的操作(出于同样的原因):在{{1}之前添加它关键字
typename
答案 1 :(得分:3)
从Effective C ++项目42:“无论何时在模板中引用嵌套的依赖类型名称,都必须在它前面加上单词typename。” size_t不嵌套在依赖于模板参数的任何内容中。你确实键入了它,但它总是size_t。
这看起来像size_type DID 依赖于模板参数。
#include <cstddef>
template< typename T >
class vector {
public:
typedef T & reference;
typedef T const & const_reference;
const_reference at( typename T::size_type ) const;
reference at( typename T::size_type );
};
template< typename T >
typename vector<T>::const_reference
vector<T>::at( typename T::size_type i ) const
{
// ...
}
template< typename T >
typename vector<T>::reference
vector<T>::at( typename T::size_type i )
{
// ...
}
struct Foo
{
typedef size_t size_type;
};
int main()
{
vector<Foo> f;
return 0;
}
size_type是Foo的嵌套类型。
答案 2 :(得分:2)
你是对的;类型需要限定,因为typedef已在类的范围内给出,而不是在全局范围内。我不知道如何在不污染全球范围的情况下美化它,这将是一个坏主意。但是,看起来你的功能很短,所以为什么不简单地将它们内联?这样可以节省很多额外的打字,恕我直言,它更容易阅读。