2020-05-24

12: An "expected primary-expression before '>' token" GCC Compile Error?

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

The error message seems not correct, and the underlying rule seems not reasonable. . . . Anyway, let me solve the problem.

Topics


About: C++

The table of contents of this article


Starting Context


  • The reader has a basic knowledge on C++.

Target Context


  • The reader will know how to solve an "expected primary-expression before '" ">" or whatever "' token" C++ GCC compile error.

Orientation


There is an article that clarifies the concept of template in C++.

There is an article that clarifies the distinction between definition and declaration in C++.


Main Body


1: Meeting an "expected primary-expression before '>' token" C++ GCC Compile Error


Hypothesizer 7
"expected primary-expression before '>' token"? What is that supposed to mean? . . .

Well, I am trying to compile this piece of C++ code with GCC (note that I put function template body declarations (which should not be called "definitions") into 'tpp' files).

theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassE.hpp

@C++ Source Code
#ifndef __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassE_hpp__
#define __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassE_hpp__

namespace theBiasPlanet {
	namespace coreUtilitiesTests {
		namespace templatesTest1 {
			class ClassE {
				public:
				    ClassE ();
				    virtual ~ClassE ();
					template <typename U> U methodE0 (U const & a_argument0) const;
			};
		}
	}
}

#endif


theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassE.cpp

@C++ Source Code
#include "theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassE.hpp"

namespace theBiasPlanet {
	namespace coreUtilitiesTests {
		namespace templatesTest1 {
			ClassE::ClassE () {
			}
			
			ClassE::~ClassE () {
			}
		}
	}
}


theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassE.tpp

@C++ Source Code
#include "theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassE.hpp"

namespace theBiasPlanet {
	namespace coreUtilitiesTests {
		namespace templatesTest1 {
			template <typename U> U ClassE::methodE0 (U const & a_argument0) const {
				return a_argument0;
			}
		}
	}
}


theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassF.hpp

@C++ Source Code
#ifndef __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassF_hpp__
#define __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassF_hpp__
	
	#include "theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassE.hpp"
	
	namespace theBiasPlanet {
		namespace coreUtilitiesTests {
			namespace templatesTest1 {
				class ClassF {
					public:
						template <typename U> static void methodF0 (U const & a_argument0);
						static void methodF1 (ClassE const & a_argument0);
				};
			}
		}
	}
#endif


theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassF.cpp

@C++ Source Code
#include "theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassF.hpp"

#include <string>

namespace theBiasPlanet {
	namespace coreUtilitiesTests {
		namespace templatesTest1 {
			void ClassF::methodF1 (ClassE const & a_argument0) {
				a_argument0.methodE0 <std::string> ("aaa");
			}
		}
	}
}


theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassF.tpp

@C++ Source Code
#include "theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassF.hpp"

#include <string>

namespace theBiasPlanet {
	namespace coreUtilitiesTests {
		namespace templatesTest1 {
			template <typename U> void ClassF::methodF0 (U const & a_argument0) {
				a_argument0.methodE0 <std::string> ("aaa");
			}
		}
	}
}

The '>' token mentioned in the message points to the '>' of 'a_argument0.methodE0 <std::string> ("aaa");'.

In the first place, what, the hell, is "primary-expression"?

This page claims that it means a building block of more complex expressions. . . . I do not know . . .

I do not know because then, I cannot imagine any expression that is not a primary-expression. In fact, what is an expression that cannot be any building block of any more complex expression? . . . For example, an expression, '1 + 2', can be a building block of '1 + 2 + 3'; so it should be a primary-expression, although the page does not seem to admit '1 + 2' to be a primary-expression . . .

Anyway, I thank that the page explicitly states that any class name like "MyClass" and "A::B" or any "template id" like "A<int>" is a primary-expression. So, 'std::string' is definitely a primary-expression, is it not? . . . The some other documents I have found seem to agree that it is really a primary-expression.

Well, the thing that is before the '>' in my code is . . . "std::string", an assured primary-expression. . . . Mr. compiler, a primary-expression seems to be already there . . .


2: Trying to Solve the Compile Error


Hypothesizer 7
The sloppiness of the message aside, that message was a reminiscent of my past struggle with template.

At that time, I had to put 'typename' in order to explicitly teach the compiler that a type name was a type name, which was for assuring that the '<'-'>' pair was for template parameterization, not for comparing things.

Well, does the compiler require 'typename'? How about this?

@C++ Source Code
				a_argument0.methodE0 <typename std::string> ("aaa");"

Nope.

Why? The compiler should now know that the '>' is not any comparison operator, should not?


3: Solving the Compile Error, and Some Complaints


Hypothesizer 7
In fact, there seems to be a rule that any template member on any template-type dependent qualification has to be explicitly declared as a template with '.template'.

Well, in my case, 'methodE0 <U>' is a template member of 'a_argument0', which is a template-type dependent qualification (certainly, it is the qualification and dependent on the template type, 'U'), so, it has to be 'a_argument0.template methodE0 <std::string> ("aaa")'.

Hmm . . . , certainly, that has solved the problem, but is such a rule reasonable? . . . I mean, I understand that the rule exists, but I do not understand why the rule is not foolish.

You know, I am not any person that is happy just because a problem has been solved without any satisfactory explanation; I want an explanation why such a rule is necessary.

For example, this (which already exists in the above code) does not cause the error.

@C++ Source Code
			void ClassF::methodF1 (ClassE const & a_argument0) {
				a_argument0.methodE0 <std::string> ("aaa");
			}

That is because, of course, the qualification is independent of any template type, escaping the premise of the rule.

However, I do not see any reason why the flagged line is more a difficulty than the passed line is, for the compiler. . . . You know, the template itself is never compiled, but instantiations of the template are compiled, right? In fact, 'void ClassF::methodF0 <ClassE> (ClassE const & a_argument0)' should be no different from 'void ClassF::methodF1 (ClassE const & a_argument0)' except the method name.

I understand that a rule that disambiguates '<' and '>' may be required, but I doubt that the present rule is wisely chosen.

If there is a reasonable necessity for the rule to exist, an understandable explanation would be nice. If the explanation is "You must just obey because I said so!", I would regard such a rule tyrannical, and foolish.


References


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