2021-03-07

19: An "unable to match function definition to an existing declaration" Visual C++ Error?

<The previous article in this series | The table of contents of this series | The next article in this series>

Not with GCC, but with Visual C++. It may concern 'typedef', and if so, it will be solved this way.

Topics


About: C++

The table of contents of this article


Starting Context


  • The reader has a basic knowledge on C++, even if he or she doesn't accurately understand its some widely-misrepresented elements.

Target Context


  • The reader will know how to solve an "unable to match function definition to an existing declaration" Visual C++ error that concerns 'typedef'.

Orientation


A standard-map-compatible elements-order-preserved map has been created in an article.

The reality of C++ template has been examined in an article.


Main Body


1: Meeting a Mysterious "unable to match function definition to an existing declaration" Compile Error, Only with Visual C++


Hypothesizer 7
This (an excerpt from a standard-map-compatible elements-order-preserved map) is compiled fine with GCC, but not with Visual C++.

'theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp'

@C++ Source Code
#ifndef __theBiasPlanet_coreUtilities_collections_NavigableLinkedMap_hpp__
	#define __theBiasPlanet_coreUtilities_collections_NavigableLinkedMap_hpp__
	
	using namespace ::std;
	
	namespace theBiasPlanet {
		namespace coreUtilities {
			namespace collections {
				template <typename T, typename U, typename W = less <T>> class NavigableLinkedMap {
					public:
						typedef T key_type;
						typedef U mapped_type;
						typedef W key_compare;
					public:
						typedef pair <key_type const, mapped_type> value_type;
						class BaseIterator {
						};
						class NonConstantIterator : public BaseIterator {
							public:
								typedef pair <key_type const, mapped_type> value_type;
								virtual value_type & operator * ();
						};
						class ConstantIterator : public BaseIterator {
							public:
								typedef pair <key_type const, mapped_type> const value_type;
								virtual value_type & operator * ();
						};
				};
			}
		}
	}
#endif

'theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.cpp'

@C++ Source Code
#include "theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp"

namespace theBiasPlanet {
	namespace coreUtilities {
		namespace collections {
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator::value_type & NavigableLinkedMap <T, U, W>::NonConstantIterator::operator * () {
				// Omitted
			}
			
			template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type & NavigableLinkedMap <T, U, W>::ConstantIterator::operator * () {
				// Omitted
			}
		}
	}
}

The error mentions "template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type & NavigableLinkedMap <T, U, W>::ConstantIterator::operator * ()" and says that it is "unable to match function definition to an existing declaration" . . .

Note that the almost the same method, "template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator::value_type & NavigableLinkedMap <T, U, W>::NonConstantIterator::operator * ()", is accepted all right. . . . Huh?


2: The Reason?


Hypothesizer 7
The only difference of the flagged one from the accepted one looks to be the name, "ConstantIterator", instead of "NonConstantIterator".

Well, is that specific name a kind of a trap? Should I change the name?

That, of course, is not the case.

Considering reasonably, the cause cannot be but the inside of "ConstantIterator::value_type". In fact, what else can it be?

It has turned out that the last "const" in "typedef pair <key_type const, mapped_type> const value_type" in the header file is the cause.

But why? What is wrong with it? . . . Honestly, I do not know.

If the "const" was eliminated in the header file and the return type in the 'cpp' file is changed to "typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type const &", the code would compile fine. Hmm . . .

But I cannot change the declaration of 'ConstantIterator::value_type', because it is a published type!. If it was changed, the compatibility with '::std::map' would be broken.

As the conclusion, I do not understand the reason, but I know the part that is causing the error.


3: A Solution


Hypothesizer 7
Well, my reasoning is that I cannot change the declaration of "ConstantIterator::value_type", so, I cannot help but not use it in the source file.

So, I have added a type, 'NonConstantvalue_type', as 'typedef pair <key_type const, mapped_type>', and changed the expression of the return type in the 'cpp' file to 'typename NavigableLinkedMap <T, U, W>::ConstantIterator::NonConstantvalue_type const &', which does not really change the return type. . . . Does that work fine? Yes.

Honestly, I am not happy about having to have such an extra otherwise-there-is-no-reason-to-exist type, but that is the best solution I have conceived of.


References


<The previous article in this series | The table of contents of this series | The next article in this series>