在查找::之前的名称期间,功能模板的名称是否应该可见? [英] Should the name of a function template be visible during lookup of a name preceding ::?

查看:52
本文介绍了在查找::之前的名称期间,功能模板的名称是否应该可见?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

clang和gcc都拒绝此代码:

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;
}

该标准说,在 :: 之前的名称的名称查找仅考虑名称空间,类型和专业为类型的模板".clang和gcc拒绝此代码正确吗?如果是这样,我想念什么?

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?

摘自C ++工作草案标准n3337

From C++ Working Draft Standard n3337

3.4.3合格名称查找[basic.lookup.qual]

3.4.3 Qualified name lookup [basic.lookup.qual]

可以在::作用域解析之后引用类或名称空间成员或枚举器的名称运算符(5.1)应用于表示其类,名称空间或枚举的嵌套名称说明符.如果一个 ::嵌套名称说明符中的作用域解析运算符之前没有decltype指定符,在::之前的名称仅考虑专门针对类型的名称空间,类型和模板.如果找到的名称未指定名称空间或类,枚举或从属类型,则该程序格式不正确.

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模板专业名称[临时名称]

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.

名称查找(3.4)后发现名称是模板名称,或者operator-function-id或literal-operator-id引用了一组重载函数,其中任何成员如果是,则为功能模板后跟< ,始终将< 用作template-argument-list的定界符,而绝不将其作为.

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.

歧义无疑是模板名称,但可以是类型或函数.可以解析整个template-id,而不必知道它是命名一个函数还是一个类型,然后在以后解决歧义.标准是否可以原谅执行者?

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?

推荐答案

问题是您引用的段落最终被申请为时已晚.在到达那里之前,编译器必须确定在 ambiguous< 3> :: value 中,< > 是模板参数定界符,且不大于和小于比.(考虑:

The problem is that the paragraph you quote ends up being applied too late. Before getting there, the compiler must determine that in ambiguous<3>::value, the < and > are template argument delimiters, and not greater than and less than. (Consider:

int ambiguous;
int value:
//  ...
int i = ambiguous<3>::value;

,解析为(歧义< 3)>:: value ,其中< > 分别小于和大于.)涉及查找歧义作为不合格的名称,并且将该符号绑定到 N :: ambiguous .之后,你被困住了在左侧的实例化模板 N :: ambiguous< 3> :: ,这是非法的.

, which parses as (ambiguous < 3) > ::value, where the < and > are less than and greater than, respectively.) This involves a lookup of ambiguous as an unqualified name, and binds the symbol to N::ambiguous. Afterwards, you're stuck with the instantiated template N::ambiguous<3> to the left of ::, which isn't legal.

这个问题可能不尽人意:仅标准请参阅第14.2节中的第3.4节,在此进行讨论,第3.4节讨论了所有可能的名称规则抬头.另一方面,实际上只有一种方法可以解释一下:编译器无法进一步解析任何内容,直到它知道歧义是否命名模板,并且可以决定以下< 是否大于或打开模板参数列表.当然,它不能重新绑定"自变量之后,一旦解析了以下标记,在一般情况下,重新绑定可能会更改< ,使解析无效.在实践中,尽管标准没有像应该说的那么清楚地说出名字查找在这种情况下,必须使用不合格的名称查找(或类成员(如果名称前面带有.-> 运算符).

This issue isn't as clear as one might like: the standard only refers to section 3.4 in section 14.2, where it discusses this, and section 3.4 discusses all of the possible rules of name lookup. On the other hand, there is really only one way to interpret it: the compiler cannot parse anything further until it knows whether ambiguous names a template or not, and can decide whether the following < is greater than, or opens a template argument list. And of course, it cannot "rebind" the argument later, once it has parsed the following tokens, since in the general case, rebinding could change the meaning of the <, invalidating the parse. In practice, although the standard doesn't say so as clearly as it probably should, the name lookup in this case must be unqualified name lookup (or class member access, if the name is preceded by a . or a -> operator).

这篇关于在查找::之前的名称期间,功能模板的名称是否应该可见?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆