I'm currently implementing containers in C and I have a question about the syntax used to declare member functions.
I have a Vector_declaration.hpp file where I declare the vector class and all its components for instance: reference operator[](size_type n);
Where reference
is defined by typedef typename Allocator::reference reference;
In another file called vector.hpp I want to implement the elements defined in Vector_declaration.hpp and I found that the only way to do that was with the following syntax:
template <typename T, typename Allocator>
typename vector<T, Allocator>::reference
vector<T, Allocator>::operator[](size_type n)
I don't understand what role typename vector<T, Allocator>::reference
plays here, why do I have to rewrite the typename
each time I use it in a function, shouldn't I be able to just use the word reference
instead?
Is there anyway to do so, so the code would be cleaner?
CodePudding user response:
Here:
template <typename T, typename Allocator>
typename vector<T, Allocator>::reference
vector<T, Allocator>::operator[](size_type n);
The typename vector<T, Allocator>::reference
is the return type of the method. Consider how it would look without templates:
struct foo {
using reference = int&;
reference bar();
};
foo::reference foo::bar() { /*...*/ }
reference
is declared in the scope of foo
. If you want to refer to it outside of the scope of foo
you need to qualify the name foo::reference
. Because this:
reference foo::bar() { /*...*/ }
would result in an error: "reference is not declared".
Moreover, typename
is needed because vector<T, Allocator>::reference
is a dependent name (ie you need to tell the compiler that it is a type, in a specialization it might be the name of a member or not exist at all).
CodePudding user response:
With trailing return type (C 11), you might do:
template <typename T, typename Allocator>
auto vector<T, Allocator>::operator[](size_type n)
-> reference
{
// ...
}
Before vector<T, Allocator>::
, you are not yet in scope class, so writing just reference
would refer to the one in global scope (::reference
).
So you can use types/using from the class in parameters and trailing return type (and in scope of the function).