What's the correct syntax for a member function of a class template returning a type defined in that class?
I am working through Accelerated C++ at the moment, and I am stuck on exercise 11-6. The idea is to reimplement the standard library vector as a class called Vec
.
I am having trouble with the iterator erase(iterator)
member, because I don't know the correct syntax when outside of the class definition, and everything I've tried results in a compiler error. The code I currently have is:
template <class T> T* Vec<T>::erase(T* pos){
if(pos < avail)
std::copy(pos + 1, avail, pos);
--avail;
alloc.destroy(avail);
return pos;
}
This works perfectly. However, for maintainability purposes and compatibility with algorithms in the stl, I know I should be doing something like this:
template <class T> Vec<T>::iterator Vec<T>::erase(Vec<T>::iterator pos){
// As before
}
I've already defined iterator
in the class definition, as follows:
typedef T* iterator;
Trying to compile with the second code snippet results in:
D:\Documents\Programming\Accelerated C++\Chapter 11>cl /EHsc Vec.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
Vec.cpp
Vec.cpp(23) : warning C4346: 'Vec<T>::iterator' : dependent name is not a type prefix with 'typename' to indicate a type
Vec.cpp(23) : error C2143: syntax error : missing ';' before 'Vec<T>::erase'
Vec.cpp(23) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Vec.cpp(23) : fatal error C1903: unable to recover from previous error(s); stopping compilation
Sadly, the warning doesn't make much sense to me, and after reading the MSDN page for it I can't exacly see how it would apply to my code.
The rest of the messages appear as if the compiler didn't recognise the return type.
I've tried many different combinations and searching hasn't been very helpful. I would appreciate any help.开发者_StackOverflow社区 Thanks!
template <class T>
typename Vec<T>::iterator Vec<T>::erase(typename Vec<T>::iterator pos){
//^^^^^^^^ note this ^^^^^^^^ note this as well!
//your code!
}
That is, typename
is required at two places. It's because iterator
is a dependent name, so typename
is required!
Read this excellent explanation by a great guy called Johannes, on Stackoverflow itself:
- Where and why do I have to put the "template" and "typename" keywords?
After reading that you can also read this topic:
- Use of typename keyword with typedef and new
Links to other good articles:
- Name binding and dependent names (C++ only)
- Dependent Names (scroll down and read this section - better if you read the complete article)
template <class T> typename Vec<T>::iterator Vec<T>::erase(typename Vec<T>::iterator pos){
// As before
}
... because iterator here is the name dependent on template parameter" without typename
compiler pretends to think that Vec::iterator is a static member of Vec :)
精彩评论