gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 17:38:10 26 4
gpt4 key购买 nike

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com