c++ - 在查找::之前的名称时,函数模板的名称是否应该可见?

标签 c++ templates language-lawyer

clang 和 gcc 都拒绝此代码:

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
}

但是,它们都接受以下代码:

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

namespace N
{
    void ambiguous();

    int i = ambiguous::value;
}

标准说在 :: 之前的名称的名称查找“只考虑专门化为类型的 namespace 、类型和模板”。 clang 和 gcc 拒绝此代码是否正确?如果是这样,我错过了什么?

来自 C++ 工作草案标准 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.

编辑

为了避免将此问题与表达式和声明之间的歧义混淆,这里是原始代码,其中模板使用类型参数而不是非类型参数。

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
}

这在所有情况下都会导致相同的错误。 <不能解释为运算符。

ambiguous是明确的模板名称,但可以是类型或函数。可以在不知道它命名的是函数还是类型的情况下解析整个 template-id,并在以后解决歧义。标准是否允许实现者不这样做?

最佳答案

问题是你引用的段落最终变成了 申请太晚了。在到达那里之前,编译器必须 确定 ambiguous<3>::value , <>是 模板参数定界符,不大于和小于 比。 (考虑:

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

,解析为 (ambiguous < 3) > ::value , 其中<>分别小于和大于。)这 涉及查找 ambiguous作为一个不合格的名字,和 将符号绑定(bind)到 N::ambiguous .之后,你被卡住了 使用实例化模板 N::ambiguous<3>至左侧 :: ,这是不合法的。

编辑:

这个问题并不像人们想象的那么清楚:只有标准 引用第 14.2 节中的第 3.4 节,其中讨论了这一点, 第 3.4 节讨论了所有可能的名称规则 抬头。另一方面,实际上只有一种方法可以 解释它:编译器不能进一步解析任何东西直到 它知道是否ambiguous是否命名模板,并且可以 决定是否以下 <大于或开 模板参数列表。当然,它不能“重新绑定(bind)” 之后的参数,一旦它解析了以下标记,因为 在一般情况下,重新绑定(bind)可能会改变 < ,使解析无效。在实践中,虽然标准 没有说得那么清楚,名称查找 在这种情况下必须是非限定名称查找(或类成员 访问,如果名称前面有 .->运营商)。

关于c++ - 在查找::之前的名称时,函数模板的名称是否应该可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18311496/

相关文章:

c++ - Halide 的性能计数器?

html - 直接在 float 图像后添加内容

c++ - 指向限定和非限定类型表示的指针

c++ - 使用声明作为覆盖

c++ - [ranges.subrange] 中 `iterator-sentinel-pair` 概念的目的是什么?

java - 与 Java nanotime() 相比,为什么 C++ 中的 clock_gettime 给我不同的值

c++ - glulookat() - 用键盘移动相机(OpenGL)

c++ - 获取 'name of the application' 以及按键

c++ - 类模板的动态实例化被认为是显式的还是隐式的?

c++ - 单例对象模板类的静态初始化