开发者

C++ using typedefs in non-inline functions

I have a class like this

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 );

and later in the same file

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 ];
}

Line X compiles fine but Line Y does not compile. The er开发者_开发知识库ror message from g++ (version 4.4.1) is:

foo.h:Y: error: expected initializer before 'vector'

From this I gather that, if I want to have non-inline functions then I have to fully qualify the typedef name as in Line X. (Note that, there is no problem for size_type.)

However, at least to me, Line X looks clumsy.

Is there any alternative approach?


Yes, in out-of-class member function definition you have to use a fully-qualified name for the nested return type. This, BTW, has nothing to do with templates. It is that way with non-template classes as well.

In your case it is a template class and, as a consequence of that, since you are using a qualified name to refer to a nested type in a dependent template class, you have to prepend it with keyword typename.

However, you only need to qualify the return type. Parameter types don't need to be qualified

template< typename T >
typename vector<T>::const_reference
  vector<T>::some_method( const_reference r ) const
{
  // ...
}

You can choose to use a qualified name for the parameter type as well, but in that case you will have to do the same thing as with the return type (for the very same reason): prepend it with typename keyword

template< typename T >
typename vector<T>::const_reference
  vector<T>::some_method( typename vector<T>::const_reference r ) const
{
  // ...
}


From Effective C++ Item 42: "anytime you refer to a nested dependent type name in a template, you must immediately precede it by the word typename." size_t is not nested inside anything dependent on a the template parameter. You did typedef it but it will always be size_t.

This is what it would look like it size_type DID depend on the template parameter.

#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 is a nested type of Foo.


You are correct; the type needs to be qualified, because your typedefs have been given in the scope of the class and not in the global scope. I do not know of any way to beautify that without polluting the global scope, which would be a bad idea. But, it looks like your functions are very short, so why don't you simply define them inline? That would save you lots of extra typing and, IMHO, it's easier to read.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜