gpt4 book ai didi

c++ - 从属名称和范围

转载 作者:行者123 更新时间:2023-12-01 14:47:19 25 4
gpt4 key购买 nike

当某些相关函数在使用之后与使用之前在范围内,有人知道编译器和/或语言标准是怎么回事吗?我在C++第四版747页中使用Stroustrup的示例的紧密副本。在DEP_NAME的示例中,可以在模板函数g之后声明Qf,它们都在范围内,但是在非DEP_NAME的示例中,则相反。
感谢您的指导!

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

最佳答案

以下所有标准引用均引用N4659: March 2017 post-Kona working draft/C++17 DIS

延迟查找相关名称允许ADL查找在函数模板定义之后声明的名称
必须在定义点声明函数模板定义中的所有非依赖名称。从属名称仅需要在第一个实例化时声明,对于给定的特化,,如果可以通过特定实例化的参数依赖查找(ADL)找到,则可以声明它们。在您的第一个示例中,g是一个从属名称,因为它取决于类型模板参数,并且可以通过::Q上的ADL找到它,因此第一个示例格式正确。在您的第二个示例中,g不是从属名称,因为它不依赖于类型模板参数,并且由于该名称在功能模板定义时不可见,因此第二个示例格式错误。
我们可以将相关标准段落中引用的规则总结为以下内容:

  • 非依赖性名称的查找遵循通常的查找规则,因此需要在函数模板定义
  • 的位置声明该名称。
  • 相关名称的查找被推迟到给定的实例化为止。但是,在此实例化时,仅仅依赖于参数的查询(ADL)将能够找到名称,这些名称不是在函数模板定义的点声明的,而是在给定实例化的点声明的。

  • 后一项目符号的规则表示以下示例格式正确:
    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:
    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)甚至会提供指示性错误消息,说明程序格式错误的原因:
    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 When looking for the declaration of a name used in a templatedefinition, the usual lookup rules ([basic.lookup.unqual],[basic.lookup.argdep]) are used for non-dependent names. The lookupof names dependent on the template parameters is postponed until theactual template argument is known ([temp.dep]). [ Example: ... ][...]


    [temp.dep.res]/1很清楚,对于非限定(相关)名称查找,仅考虑在模板定义时可见的声明[ 强调矿]:

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

    • (1.1) Declarations that are visible at the point of definition of the template.
    • (1.2) Declarations from namespaces associated with the types of the function arguments both from the instantiation context ([temp.point])and from the definition context.

    [temp.dep.candidate]/1 [ 强调地雷]中重复的事实:

    [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) 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 eitherthe template definition context or the template instantiation contextare found.

    关于c++ - 从属名称和范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62984097/

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