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

Discussion in 'C++' started by Lawrence Spector, Jul 12, 2007.

  1. 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
     
    Lawrence Spector, Jul 12, 2007
    #1
    1. Advertising

  2. Lawrence Spector wrote:
    > 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<T>' to 'T').

    > }
    > };
    >
    > 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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jul 12, 2007
    #2
    1. Advertising

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

    * 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".


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 12, 2007
    #3
  4. Lawrence Spector wrote:

    > 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<int>();

    > }
    > };
    >
    > 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.

    --
    rbh
     
    Robert Bauck Hamar, Jul 12, 2007
    #4
  5. 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
     
    Lawrence Spector, Jul 12, 2007
    #5
  6. Lawrence Spector wrote:
    > 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<T*>(this)->template callMethod<int>();

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


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jul 12, 2007
    #6
  7. Re: Dependent Template Issue? g++ gives the following ==> error:expected primary-expression before "int"

    * 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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 12, 2007
    #7
  8. On Jul 12, 4:16 pm, "Victor Bazarov" <> wrote:
    > Lawrence Spector wrote:
    > > 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<T*>(this)->template callMethod<int>();
    >
    > > 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.

    On Jul 12, 4:17 pm, "Alf P. Steinbach" <> wrote:
    > 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.
     
    Lawrence Spector, Jul 12, 2007
    #8
  9. On Jul 12, 4:16 pm, "Victor Bazarov" <> wrote:
    > Lawrence Spector wrote:
    > > 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<T*>(this)->template callMethod<int>();
    >
    > > 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.
     
    Lawrence Spector, Jul 12, 2007
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Schnoffos
    Replies:
    2
    Views:
    1,221
    Martien Verbruggen
    Jun 27, 2003
  2. Replies:
    3
    Views:
    3,348
    Earl Purple
    Oct 5, 2006
  3. puzzlecracker
    Replies:
    1
    Views:
    523
    James Kanze
    Aug 7, 2008
  4. AAaron123
    Replies:
    0
    Views:
    554
    AAaron123
    Mar 12, 2009
  5. carl
    Replies:
    7
    Views:
    2,750
    Johannes Schaub (litb)
    Dec 6, 2009
Loading...

Share This Page