从属名称和范围 [英] Dependent name and scope

查看:72
本文介绍了从属名称和范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用之前和之后,某些相关函数在范围内时,有人知道编译器和/或语言标准是怎么回事吗?我正在使用C ++第四版747页中的Stroustrup示例的紧密副本.在DEP_NAME示例中,可以在模板函数 f <之后声明 g Q /code>并在范围内,但是在非DEP_NAME示例中,则相反.

Does anyone know what is going on with the compiler and/or language standard when certain dependent functions are in scope after vs before use? I'm using a close copy of Stroustrup's example in C++ 4th Ed Page 747. In the DEP_NAME example g and Q can be declared after the template function f and are in scope, however in the non DEP_NAME example the opposite is true.

感谢您的指导!

#define DEP_NAME
#ifdef DEP_NAME
template<typename T> T f(T a)
{
    return g(a); // OK: a is a dependent name and therefore so is g
}
// can be declared after f
class Q { };
Q g(Q e)
{
    return e;
}
#else
// must be declared before f
class Q { };
Q g(Q e)
{
    return e;
}
template<typename T> T f(T a)
{
    return g(Q{});
}
#endif

int main(int argc, char *argv[])
{
    Q z = f(Q{});
    return 0;
}

推荐答案

以下所有标准参考文献均引用必须在定义点声明函数模板定义中的所有非相关名称.对于给定的专业化,如果,可以通过特定实例的参数依赖查找(ADL)找到相关名称,只需在第一次实例化时声明相关名称.在您的第一个示例中, g 是从属名称,因为它取决于类型模板参数,并且可以通过ADL在 :: Q 上找到它,因此第一个例子格式正确.在您的第二个示例中, g 不是从属名称,因为它不依赖于类型模板参数,并且由于该名称在函数模板定义时不可见,因此第二个示例是错误的形成.

All non-dependent names in a function template definition must be declared at the point of the definition. Dependent names need only be declared at the time of the first instantiation, for a given specialization, if they can be found via argument-dependent lookup (ADL) for the particular instantiation. In your first example, g is a dependent name as it depends on the type template parameter, and it can moreover be found via ADL on ::Q, and thus the first example is well-formed. In your second example g is not a dependent name as it does not depend on the type template parameter, and as the name is moreover not visible at the point of the function template definition, the second example is ill-formed.

我们可以将相关标准段落中引用的规则总结如下(请参见详细信息部分):

We can summarize the rules quoted from the relevant standard passages (see Section Details) as:

  • 非相关名称的查找遵循通常的查找规则,因此需要在函数模板定义时声明该名称
  • 查找从属名称被推迟到给定的实例化为止.但是,在实例化时,仅依赖于参数的查找(ADL)将能够找到在函数模板定义时未声明的名称但在给定的实例化点被声明.
  • Lookup for non-dependent names follows the usual lookup rules, and thus the name need to be declared at the point of the function template definition,
  • Lookup for dependent names is postponed until a given instantiation. However, at the time of this instantiation, only argument-dependent lookup (ADL) will be able to find names that were not declared at the point of the function template definition, but were declared at the point of the given instantiation.

后面的项目符号规则意味着下面的示例格式正确:

The rules of latter bullet means that the following example is well-formed:

namespace ns {

template<typename T> T f(T a) {
    // Can find ::ns::g(Q) only via ADL on T for
    // an instantiation of f with T == ::ns::Q.
    return g(a);
}

class Q {};

Q g(Q e) { return e; }

}  // namespace ns

int main() {
    (void) f(ns::Q{});
    return 0;
}

如以下示例所示:

template<typename T> T f(T a) {
    // Can find ::ns::g(Q) only via ADL on T for
    // an instantiation of f with T == ::ns::Q.
    return g(a);
}

namespace ns {

class Q {};

Q g(Q e) { return e; }

}  // namespace ns

int main() {
    (void) f(::ns::Q{});
    return 0;
}

以下示例格式错误,因为ADL找不到 g :: ns :: Q :

whereas the following example is ill-formed, as ADL cannot find g for an instantiation of ::ns::Q:

template<typename T> T f(T a) {
    // Cannot find ::g(Q) as ADL on T for
    // an instantiation of f with T == ::ns::Q
    // will only consider the ::ns namespace.
    return g(a);
}

namespace ns {

class Q {};
    
}  // namespace ns  

::ns::Q g(::ns::Q e) { return e; }

int main() {
    (void) f(::ns::Q{});
    return 0;
}

对于后者,编译器(在这种情况下为Clang)甚至会给出指示性的错误消息,说明程序格式错误的原因:

For the latter, the compiler (in this case, Clang) even presents an instructive error message as for why the program is ill-formed:

error: call to function 'g' that is neither visible in the template
       definition nor found by argument-dependent lookup


详细信息

[temp.res]/9 状态[摘录,强调我的]:

[temp.res]/9 在查找模板中使用的名称的声明时定义,通常的查找规则([[basic.lookup.unqual],[basic.lookup.argdep])用于非依赖性名称.查询取决于模板参数的名称被推迟到实际的模板参数是已知的([temp.dep]).[ 例子: ... ][...]

[temp.res]/9 When looking for the declaration of a name used in a template definition, the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) are used for non-dependent names. The lookup of names dependent on the template parameters is postponed until the actual template argument is known ([temp.dep]). [ Example: ... ] [...]

[temp.dep.res]/1 很明显,只有在模板定义时可见的声明才被考虑用于非限定(相关)名称查找[强调我的]:

[temp.dep.res]/1 is clear that only declarations that are visible at the point of definition of the template are considered for non-qualified (dependent) name lookup [emphasis mine]:

[temp.dep.res]/1 在解析从属名称时,来自以下来源的名称为考虑过:

[temp.dep.res]/1 In resolving dependent names, names from the following sources are considered:

  • (1.1)在模板定义时可见的声明.
  • (1.2)来自实例化上下文([temp.point])中与函数自变量类型相关联的名称空间的声明 在定义上下文中.

[temp.dep.候选人]/1 [强调我的]:

[temp.dep.candidate]/1 对于后缀表达式为从属名称的函数调用,使用常规查找规则找到候选函数([basic.lookup.unqual],[basic.lookup.argdep]),除了:

[temp.dep.candidate]/1 For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:

  • (1.1)对于使用非限定名称查找的部分查找,仅从模板定义上下文中找到函数声明.
  • (1.2)对于使用关联名称空间([basic.lookup.argdep])的部分,仅在中找到函数声明模板定义上下文或模板实例化上下文找到.
  • (1.1) For the part of the lookup using unqualified name lookup, only function declarations from the template definition context are found.
  • (1.2) For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.

这篇关于从属名称和范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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