Take a look at this peice of code:
template
Pointer::Iterator> BinaryTree::GetBegi
For those interested, I tried writing a minimal sample reproducing the problem:
template <typename T>
struct Pointer {};
template <typename T>
struct Collection {
struct Iterator {};
};
template <typename K,typename T>
struct BinaryTree : Collection<T>{
Pointer<typename Collection<T>::Iterator> GetBeginning() const;
struct BinaryTreeIterator : Collection<T>::Iterator {
template <typename X>
BinaryTreeIterator(BinaryTreeIterator*, X) {}
struct Position {
static int atBeginning() { return 0; }
};
};
};
template <typename K,typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return Pointer<typename Collection<T>::Iterator>();
}
int main(){
BinaryTree<int, float> bt;
bt.GetBeginning();
}
And yes, I get the error too. I can't see any obvious errors in what we've seen of your code, but then again, just this example has used more nested classes and inheritance than most sane C++ programmers do in a year, so I can't say for sure that your code is or isn't correct.
Moreover, I've had to guess quite a bit to piece this together. (What's atBeginning supposed to be? What are the actual class interfaces?)
But I suspect it'd work better (and be more readable and easier to debug) if you didn't inherit everything from everything else.
Update I tried compiling the above with GCC and Comeau's online compiler, and both accepted it. So it seems like it could be a compiler bug.
The obvious solution which you probably considered is to just define the function inside the class definition instead of redefining it later.
Also, Putting the iterator type in a typedef like so:
template <typename T>
struct Pointer {};
template <typename T>
struct Collection {
struct Iterator {};
};
template <typename K,typename T>
struct BinaryTree : Collection<T>{
typedef typename Collection<T>::Iterator Iter;
Pointer<Iter> GetBeginning() const;
struct BinaryTreeIterator : Collection<T>::Iterator {
};
};
template <typename K,typename T>
Pointer<typename BinaryTree<K,T>::Iter> BinaryTree<K,T>::GetBeginning() const
{
return new BinaryTreeIterator(this,BinaryTreeIterator::Position::atBeginning);
}
int main(){
BinaryTree<int, float> bt;
bt.GetBeginning();
}
seems to fix it. Not sure why, possibly a bug...
It will compile if you change it to this:
template <typename K,typename T>
struct BinaryTree : Collection<T> {
Pointer<typename BinaryTree<K,T>::Iterator> GetBeginning() const;
};
template <typename K,typename T>
Pointer<typename BinaryTree<K,T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return Pointer<BinaryTree<K,T>::Iterator>();
}
In general, the original code isn't quite right because it implies that GetBeginning() can return any collection, while (I'm assuming) it can only return binary tree collections.
EDIT:
After some digging, it seems that VC++ doesn't handle well injected class names. That is, the original code will compile if you remove from Collection::Iterator in the method declaration:
template <typename K, typename T>
struct BinaryTree : Collection<T> {
Pointer<typename Collection::Iterator> GetBeginning() const;
};
template <typename K, typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return Pointer<Collection<T>::Iterator>();
}