tags:

views:

80

answers:

2

I have the following test code

#include <iostream>
template <typename T>

struct PS
{
   template <typename U>
   static void foo()
   {
       std::cout<<"Some test code";
   }
};

template <typename T>
void bar()
{
   PS<T>::template foo<T>(); //won't compile without `::template`
}

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

ISO C++03 14.2/4: says

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.

The Standard talks about -> and . but not about ::. Is it a defect in the C++03 Standard or am I missing something? Someone please enlighten me.

However the wording has been changed in N3126

When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object or pointer expression of the postfix-expression or the nested-name-specifier in the qualified-id depends on a template parameter (14.6.2) but does not refer to a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

Can someone give an example to illustrate what but does not refer to a member of the current instantiation means in context of C++0x?

-PS

+5  A: 

The Standard talks about -> and . but not about ::.

The scope resolution operator (::) is part of the qualified-id referred to by "or after nested-name-specifier in a qualified-id."

The additional verbiage in C++0x is part of the resolution to CWG defect 224. Effectively, the definition of dependent names has been changed:

The decision on whether a name is dependent or non-dependent should be based on lookup, not on the form of the name: if the name can be looked up in the definition context and cannot be anything else as the result of specialization, the name should be non-dependent.

James McNellis
Note that the Standard's use of "qualified-id" is wrong on many places, so best don't take it by word when it says "qualified-id". In the following variable declaration, for example, you need `::template`, but the nested name specifier does not appear in a qualified-id (but is nested in a `type-specifier`): `typename T::template alloc<int> a;`. In fact, the use of "qualified-id" in the Standard most often reflects the intent of meaning "qualified name".
Johannes Schaub - litb
+3  A: 

Can someone give an example to illustrate what "but does not refer to a member of the current instantiation" means in context of C++0x?

I don't know if this is something that in fact behaves differently between an implementation of C++03 and C++0x.

template< typename Q >
struct A {
    template< typename T >
    void f( T );

    void g() {
        this->f< Q >( 5 ); // member of current instantiation is not ambiguous

        A< identity<Q> >().template f< 5 >(); // suppose A is partially 
// specialized on identity. Legal but confusing; need help from template keyword.
    }
};
Potatoswatter