4

Is it possible to pass object of a class with templated method as a template parameter under GCC? All search I conducted pointed me to questions regarding templated class, which is not applicable in my case.

Sample code:

#include <iostream>

class Foo
{
public:
    template<typename T>
    void print(const T& arg) const
    {
        std::cout << arg << std::endl;
    }
};

template<typename A>
void print(const A& printer)
{
    printer.print<int>(1);
}

int main()
{
    Foo foo;
    print<Foo>(foo);
    return 0;
}

Compiling under MinGW.org GCC-6.3.0-1 I get the following results:

tmpl.cpp: In function 'void print(const A&)':
tmpl.cpp:16:19: error: expected primary-expression before 'int'
     printer.print<int>(1);
                   ^~~
tmpl.cpp:16:19: error: expected ';' before 'int'

VisualStudio compiles the same code cleanly, application works as expected. If I make print function not templated, so that is explicitly takes object of Foo it works as expected both compilers.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Darth Hunterix
  • 1,484
  • 5
  • 27
  • 31
  • 1
    Interesting to see duplicates 4 times upvote. Is a criteria for upvote that there was own research ;) – Klaus Jul 17 '18 at 10:51

2 Answers2

3

You need to use template keyword to tell that print is a template.

Inside a template definition, template can be used to declare that a dependent name is a template.

e.g.

template<typename A>
void print(const A& printer)
{
    printer.template print<int>(1);
    //      ~~~~~~~~
}

print is a dependent name, it depends on the template parameter A. Before the template gets instantiated the compiler knows nothing about A; so you need to add the template keyword to tell the compiler that print is a template, then the < after the name print is valid; otherwise < will be treated as the operator< then cause the error.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 1
    Admittedly, I find this syntax quite confusing.... – lubgr Jul 17 '18 at 10:20
  • @lubgr I added some explanations, hope could help you to understand it.. – songyuanyao Jul 17 '18 at 10:24
  • Thanks, the explanation is clear and I understand why the keyword is needed at this point. It's just being so used to a member variable/function after the dot, and in particular no spaces between instance and member var./fct. (even though there could be). – lubgr Jul 17 '18 at 10:28
  • @lubgr You'll get used to it; it's quite a common issue in c++ templates. – songyuanyao Jul 17 '18 at 10:30
  • Thanks for the help, both answers are correct, but I marked your as more thorough :) – Darth Hunterix Jul 17 '18 at 10:37
3

You need the template keyword in order to specify that print() is a template, like this:

printer.template print<int>(1);
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • @Klaus I wanted to check it first in the compiler. However I see that the other answer was edited, which makes it a bit different. :) I saw the duplicate, you are right, marked that! ;) – gsamaras Jul 17 '18 at 10:18
  • It was only for fun! And it is also a duplicate: https://stackoverflow.com/questions/3505713/c-template-compilation-error-expected-primary-expression-before-token – Klaus Jul 17 '18 at 10:19
  • Thanks for the help :) It would seem that my google-fu needs a level-up, as I failed to locate that question :) Indeed it is a duplicate, with the possible difference that my title fits a different combination of keywords :) – Darth Hunterix Jul 17 '18 at 10:36
  • 1
    @DarthHunterix we all have been in this situation! =) Thanks for the nice question, deserved my upvote. You did well to accept the other answer, since after its edit, it's more complete than mine. – gsamaras Jul 17 '18 at 10:37