tags:

views:

588

answers:

3

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?

Edit: Added main() and the compiler error.

A: 

Where is the type T defined ?

When you call function g() at that time type T must be known else get ready for compiler error saying that T is undefined.

Ashish
If you call g(), you will more likely get an error "Missing template argument"
drhirsch
yes you are correct
Ashish
+22  A: 

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

Kirill V. Lyadvinsky
This link also explains why: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/keyword_template_qualifier.htm
Space_C0wb0y
well spotted - I'm always forgetting that one. The fact that VC++ lets it past without doesn't help
Phil Nash
Well... Who woulda thunk it! I've never seen this syntax before. Thanks.
Ari
Space_C0wb0y, thanks for the link.
Ari
Future standards (C++0x) still require `template` here. Some compilers are just not standard's conforming (VC++).
Johannes Schaub - litb
Yes, it still there. Found it in draft n2857.
Kirill V. Lyadvinsky
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.
Johannes Schaub - litb
Strange to hear that. I've tried Comeau and it gives the error `line 8: error: expected an expression`.
Kirill V. Lyadvinsky
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 :)
Johannes Schaub - litb
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).
Johannes Schaub - litb
A: 

Could you specify what compiler you are using? The code in the question, with

int main() {
   g<int>();
}

added compiled without problem using cl.exe from Microsoft Visual Studio 9;

It failed on various versions of G++ I tried, and the Comeau online compiler too.

grrussel