Dependent Template Issue? g++ gives the following ==> error: expected primary-expression before "int

L

Lawrence Spector

I ran into a problem using g++. Visual Studio 2005 never complained
about this, but with g++ I ran into this error. I can't figure out if
I've done something wrong or if this is a compiler bug. Here's a very
simple example which should illustrate what I'm doing.

#include <iostream>

template <class T>
class TestBase
{
public:
TestBase() {}

int testMethod()
{
return T::callMethod<int>(); // ERROR?
}
};

class Derived : public TestBase<Derived>
{
public:
Derived() : TestBase<Derived>() {}


template <class T>
T callMethod()
{
return T();
}
};

int main()
{
Derived derived;

int x = derived.callMethod<int>();
int y = derived.testMethod(); // CALLED FROM HERE

return 0;
}


Results in the following:

$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod()':
GccTemplateCompile.cpp:12: error: expected primary-expression before
"int"
GccTemplateCompile.cpp:12: error: expected `;' before "int"
GccTemplateCompile.cpp:12: error: expected primary-expression before
"int"
GccTemplateCompile.cpp:12: error: expected `;' before "int"

Does anyone have any idea what's going on?

Thanks in advance,

Lawrence
 
V

Victor Bazarov

Lawrence said:
I ran into a problem using g++. Visual Studio 2005 never complained
about this, but with g++ I ran into this error. I can't figure out if
I've done something wrong or if this is a compiler bug. Here's a very
simple example which should illustrate what I'm doing.

#include <iostream>

template <class T>
class TestBase
{
public:
TestBase() {}

int testMethod()
{
return T::callMethod<int>(); // ERROR?

Add the keyword template:

return T::template callMethod<int>();

Also, it is most likely that it's not going to work since
even if 'callMethod' is a member of 'T', you would need
an instance of 'T' to call non-static member function. If
you hope to use 'this' here, it shouldn't work because
there is no convestion from 'this' (which is of the type
'TestBase said:
}
};

class Derived : public TestBase<Derived>
{
public:
Derived() : TestBase<Derived>() {}


template <class T>
T callMethod()
{
return T();
}
};

int main()
{
Derived derived;

int x = derived.callMethod<int>();
int y = derived.testMethod(); // CALLED FROM HERE

return 0;
}


Results in the following:

$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod()':
GccTemplateCompile.cpp:12: error: expected primary-expression before
"int"
GccTemplateCompile.cpp:12: error: expected `;' before "int"
GccTemplateCompile.cpp:12: error: expected primary-expression before
"int"
GccTemplateCompile.cpp:12: error: expected `;' before "int"

Does anyone have any idea what's going on?

The compiler does not know that 'callMethod' is a template member.

V
 
A

Alf P. Steinbach

* Lawrence Spector:
I ran into a problem using g++. Visual Studio 2005 never complained
about this, but with g++ I ran into this error. I can't figure out if
I've done something wrong or if this is a compiler bug. Here's a very
simple example which should illustrate what I'm doing.

#include <iostream>

template <class T>
class TestBase
{
public:
TestBase() {}

int testMethod()
{
return T::callMethod<int>(); // ERROR?

Yes, unless "callMethod" is a static member of "T".
 
R

Robert Bauck Hamar

Lawrence said:
I ran into a problem using g++. Visual Studio 2005 never complained
about this, but with g++ I ran into this error. I can't figure out if
I've done something wrong or if this is a compiler bug. Here's a very
simple example which should illustrate what I'm doing.

#include <iostream>

template <class T>
class TestBase
{
public:
TestBase() {}

int testMethod()
{
return T::callMethod<int>(); // ERROR?

return T::template callMethod<int>();

would be the correct syntax. The template keyword says that the following
name is a template, and thus that a following < is not the less than
operator. This is needed because the compiler at this time cannot know what
the members of T is.

But as callMethod is a nonstatic member function, you cannot do this. If you
had a T object, you could do:

T t;
return t.template callMethod said:
}
};

class Derived : public TestBase<Derived>
{
public:
Derived() : TestBase<Derived>() {}


template <class T>
T callMethod()
{
return T();
}
};

int main()
{
Derived derived;

int x = derived.callMethod<int>();

Here, you shouldn't use the template keyword, because the compiler already
know what a Derived object contains.
int y = derived.testMethod(); // CALLED FROM HERE

return 0;
}


Results in the following:

$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod()':
GccTemplateCompile.cpp:12: error: expected primary-expression before
"int"
GccTemplateCompile.cpp:12: error: expected `;' before "int"
GccTemplateCompile.cpp:12: error: expected primary-expression before
"int"
GccTemplateCompile.cpp:12: error: expected `;' before "int"

Does anyone have any idea what's going on?

You have to tell the compiler that you are using a template, because at the
time, the compiler cannot tell if T::callMethod is a template.

If you look at the error message, it makes sense if you know that the
compiler thinks it is about to parse a less than expression: It has found
T::callMethod, and the standard says that it should assume it is an object,
and a < operator to use with this object as left hand side.
 
L

Lawrence Spector

My response doesn't look like it went through, so let me try again.

I added the template so it now looks like this:

template <class T>
class TestBase
{
public:
TestBase() {}

int testMethod()
{
return T::template callMethod<int>(); // ERROR?
}

};

As mentioned, this results in a different problem, shown below:

$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod() [with
T = Derived]':
GccTemplateCompile.cpp:33: instantiated from here
GccTemplateCompile.cpp:11: error: cannot call member function `T
Derived::callMe
thod() [with T = int]' without object


Now, the issue you guys is say is that I don't have an instance. And
yet, I should, because that class is a derivative of this one. Does
the curiously recurring template pattern not work in g++?

Regardless, what's the proper way to do this in C++?

Thanks again,

Lawrence
 
V

Victor Bazarov

Lawrence said:
My response doesn't look like it went through, so let me try again.

I added the template so it now looks like this:

template <class T>
class TestBase
{
public:
TestBase() {}

int testMethod()
{
return T::template callMethod<int>(); // ERROR?
}

};

As mentioned, this results in a different problem, shown below:

$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod() [with
T = Derived]':
GccTemplateCompile.cpp:33: instantiated from here
GccTemplateCompile.cpp:11: error: cannot call member function `T
Derived::callMe
thod() [with T = int]' without object


Now, the issue you guys is say is that I don't have an instance. And
yet, I should, because that class is a derivative of this one.

So what? In a base class member, 'this' is not implicitly convertible
to any derived class. If you insist (and your 'TestBase' knows that
'T' derives from it), do

static_cast said:
Does
the curiously recurring template pattern not work in g++?

Regardless, what's the proper way to do this in C++?

V
 
A

Alf P. Steinbach

* Lawrence Spector:
My response doesn't look like it went through, so let me try again.

I added the template so it now looks like this:

template <class T>
class TestBase
{
public:
TestBase() {}

int testMethod()
{
return T::template callMethod<int>(); // ERROR?

Yes, unless "callMethod" is a static member of "T".

Hey, I already told you that.

Why don't you read the responses you get?

}

};

As mentioned, this results in a different problem, shown below:

$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod() [with
T = Derived]':
GccTemplateCompile.cpp:33: instantiated from here
GccTemplateCompile.cpp:11: error: cannot call member function `T
Derived::callMe
thod() [with T = int]' without object


Now, the issue you guys is say is that I don't have an instance. And
yet, I should, because that class is a derivative of this one. Does
the curiously recurring template pattern not work in g++?

Regardless, what's the proper way to do this in C++?

Depends what you're trying to achieve. You can, for example,

* Make callMethod a static member.
* Downcast the "this" pointer and call through that.
* Use a virtual function and no templates.
* Pass a function pointer.
* Even a switch construction might be appropriate.

All depending on what exactly you're trying to achieve.

Context does matter, and you haven't provided any hint, not a single
clue, about what the gnargle-gnargle you're trying to achieve.
 
L

Lawrence Spector

Lawrence said:
My response doesn't look like it went through, so let me try again.
I added the template so it now looks like this:
template <class T>
class TestBase
{
public:
TestBase() {}
int testMethod()
{
return T::template callMethod<int>(); // ERROR?
}

As mentioned, this results in a different problem, shown below:
$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod() [with
T = Derived]':
GccTemplateCompile.cpp:33: instantiated from here
GccTemplateCompile.cpp:11: error: cannot call member function `T
Derived::callMe
thod() [with T = int]' without object
Now, the issue you guys is say is that I don't have an instance. And
yet, I should, because that class is a derivative of this one.

So what? In a base class member, 'this' is not implicitly convertible
to any derived class. If you insist (and your 'TestBase' knows that
'T' derives from it), do

static_cast said:
Does
the curiously recurring template pattern not work in g++?
Regardless, what's the proper way to do this in C++?

V

Gotcha. I'm past the problem. Thanks for the help.

Yes, unless "callMethod" is a static member of "T".

Hey, I already told you that.

Why don't you read the responses you get?

Just to clarify before any misunderstandings, I read the suggestions
and then tried them for myself to try to enhance my understanding of
the issue. My understanding is now enhanced. Thanks.

Thanks for the assistance, everyone. I very much appreciate it.
 
L

Lawrence Spector

Lawrence said:
My response doesn't look like it went through, so let me try again.
I added the template so it now looks like this:
template <class T>
class TestBase
{
public:
TestBase() {}
int testMethod()
{
return T::template callMethod<int>(); // ERROR?
}

As mentioned, this results in a different problem, shown below:
$ g++ -c GccTemplateCompile.cpp
GccTemplateCompile.cpp: In member function `int
TestBase<T>::testMethod() [with
T = Derived]':
GccTemplateCompile.cpp:33: instantiated from here
GccTemplateCompile.cpp:11: error: cannot call member function `T
Derived::callMe
thod() [with T = int]' without object
Now, the issue you guys is say is that I don't have an instance. And
yet, I should, because that class is a derivative of this one.

So what? In a base class member, 'this' is not implicitly convertible
to any derived class. If you insist (and your 'TestBase' knows that
'T' derives from it), do

static_cast said:
Does
the curiously recurring template pattern not work in g++?
Regardless, what's the proper way to do this in C++?

V

Gotcha. I'm past the problem.

Thanks for the assistance, everyone.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top