Take a look at this peice of code:
template <typename K,typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return new BinaryTreeIterator(this,BinaryTreeIterator::Position::atBeginning);
}
When I try to compile it using VSTS 2008, I get:
error C2244: 'BinaryTree<K,T>::GetBeginning' : unable to match function definition to an existing declaration
see declaration of 'BinaryTree<K,T>::GetBeginning'
2> definition
2> 'Pointer<Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning(void) const'
2> existing declarations
2> 'Pointer<Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning(void) const'
The declaration:
Pointer<Iterator> GetBeginning() const;
is inside the class. BinaryTree indirectly inherits from Collection, and BinaryTreeIterator indirectly inherits from Iterator, both nested classes of their respective containers.
You can easily see that even in the error report, both definition and declaration are identical. Is there really something wrong here?
I found that microsoft released a hotfix: "Certain template code does not compile, and error C2244 occurs after you install Visual Studio 2005 Service Pack 1". However I couldn't find any reference to VSTS 2008.
So first I wanted to check if anybody could spot a real error in the code at a glance, and if it's VS's fault, does anyone know if the above hotfix is the solution and is relevant for 2008 as well.
For those interested, I tried writing a minimal sample reproducing the problem:
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.
It will compile if you change it to this:
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:
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:
seems to fix it. Not sure why, possibly a bug...