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
- Target Context
- Orientation
- Main Body
- 1: Meeting an "expected primary-expression before '>' token" C++ GCC Compile Error
- 2: Trying to Solve the Compile Error
- 3: Solving the Compile Error, and Some Complaints
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.