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?


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!