Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should the name of a function template be visible during lookup of a name preceding ::?

Tags:

Both clang and gcc reject this code:

template<int i>
struct ambiguous
{
    static const int value = i;
};

namespace N
{
    template<int i>
    void ambiguous();

    int i = ambiguous<3>::value; // finds the function template name
}

However, they both accept the following code:

struct ambiguous
{
    static const int value = 0;
};

namespace N
{
    void ambiguous();

    int i = ambiguous::value;
}

The standard says that name lookup of a name preceding :: "considers only namespaces, types, and templates whose specializations are types". Are clang and gcc correct in rejecting this code? If so, what am I missing?

From C++ Working Draft Standard n3337

3.4.3 Qualified name lookup [basic.lookup.qual]

The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a :: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types. If the name found does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed.

14.2 Names of template specializations [temp.names]

For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.

After name lookup (3.4) finds that a name is a template-name or that an operator-function-id or a literal-operator-id refers to a set of overloaded functions any member of which is a function template if this is followed by a <, the < is always taken as the delimiter of a template-argument-list and never as the less-than operator.

Edit

To avoid confusion of this issue with the ambiguity between an expression and a declaration, here is the original code with the templates using a type parameter instead of a non-type parameter.

template<class>
struct ambiguous
{
    static const int value = 0;
};

namespace N
{
    template<class>
    void ambiguous();

    int i = ambiguous<int>::value; // finds the function template name
}

This results in the same error in all cases. The < cannot be interpreted as an operator.

ambiguous is unambiguously a template-name, but could either be a type or a function. It's possible to parse the entire template-id without knowing whether it names a function or a type, and resolve the ambiguity later on. Does the standard excuse the implementor from doing this?