template member function of template class called from template function [duplicate]
Asked Answered
Q

1

49

This doesn't compile:

template<class X> struct A {
   template<int I> void f() {}
};

template<class T> void g()
{
   A<T> a;
   a.f<3>();  // Compilation fails here (Line 18)
}

int main(int argc, char *argv[])
{
   g<int>();  // Line 23
}

The compiler (gcc) says:

hhh.cpp: In function 'void g()':

hhh.cpp:18: error: expected primary-expression before ')' token

hhh.cpp: In function 'void g() [with T = int]':

hhh.cpp:23: instantiated from here

hhh.cpp:18: error: invalid use of member (did you forget the '&' ?)

Can anyone explain why this is? Is there a way to get it to work?

Quesenberry answered 3/12, 2009 at 14:37 Comment(2)
What does the compiler complain about?Refrigeration
It works for me. How are you invoking g() ? (and what error are you getting, as others have asked?)Autostability
B
85

Try the following code:

template<class T> void g()
{
   A<T> a;
   a.template f<3>();  // add `template` keyword here
}

According to C++'03 Standard 14.2/4:

When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

Future C++ Standard seems to be still require this keyword according to draft n2857 14.3/4. Some compilers has special mode that allows to compile original code without errors (Comeau compiles it in so called relaxed mode).

Bim answered 3/12, 2009 at 14:45 Comment(9)
This link also explains why: publib.boulder.ibm.com/infocenter/comphelp/v8v101/…Cental
well spotted - I'm always forgetting that one. The fact that VC++ lets it past without doesn't helpAutostability
Well... Who woulda thunk it! I've never seen this syntax before. Thanks.Quesenberry
Future standards (C++0x) still require template here. Some compilers are just not standard's conforming (VC++).Carry
Yes, it still there. Found it in draft n2857.Bim
I tried the code with comeau online compiler, which accepts it even in the strictest settings: What happened is that it apparently optimized away the local object and didn't care. If you call return a.f<3>(); instead (and make it return something), it will error out too. This looks like a optimizer bug to me.Carry
Strange to hear that. I've tried Comeau and it gives the error line 8: error: expected an expression.Bim
Notice the weird wording of "explicitly depends". In early pre-standard drafts, names could explicitly and implicitly depend on template arguments. Nowadays, there is no such difference anymore, but the "explictly" is still apparent in some places :)Carry
Furture Standard will not require it only when the template can be looked up already ("member of the current instantiation"). If you do template<typename T> struct A { template<typename U> void f(); void g() { this->f<int>(); } }; then it will go fine because f is a "member of the current instantiation" (but only in C++0x, not in C++03).Carry

© 2022 - 2024 — McMap. All rights reserved.