在C++ 20中什么是decl-reachable?

icnyk63a  于 2022-12-01  发布在  其他
关注(0)|答案(1)|浏览(126)

§10.4/3详细给出了decl-reachable的所有可能的情况,但是我不能完全理解,考虑一下§10.4/6中描述的例子:

Source file "foo.h":
  namespace N {
  struct X {};
  int d();
  int e();
  inline int f(X, int = d()) { return e(); }
  int g(X);
  int h(X);
}

Module M interface:
module;
#include "foo.h"
export module M;
template<typename T> int use_f() {
  N::X x;                       // N​::​X, N, and ​::​ are decl-reachable from use_­f
  return f(x, 123);             // N​::​f is decl-reachable from use_­f,
                                // N​::​e is indirectly decl-reachable from use_­f
                                //   because it is decl-reachable from N​::​f, and
                                // N​::​d is decl-reachable from use_­f
                                //   because it is decl-reachable from N​::​f
                                //   even though it is not used in this call
}
template<typename T> int use_g() {
  N::X x;                       // N​::​X, N, and ​::​ are decl-reachable from use_­g
  return g((T(), x));           // N​::​g is not decl-reachable from use_­g
}
template<typename T> int use_h() {
  N::X x;                       // N​::​X, N, and ​::​ are decl-reachable from use_­h
  return h((T(), x));           // N​::​h is not decl-reachable from use_­h, but
                                // N​::​h is decl-reachable from use_­h<int>
}
int k = use_h<int>();
  // use_­h<int> is decl-reachable from k, so
  // N​::​h is decl-reachable from k

Module M implementation:
module M;
int a = use_f<int>();           // OK
int b = use_g<int>();           // error: no viable function for call to g;
                                // g is not decl-reachable from purview of
                                // module M's interface, so is discarded
int c = use_h<int>();           // OK

为什么N​::​g不能从use_­g声明可达?为什么N​::​h不能从use_­h声明可达,而N​::​h可以从use_­h<int>声明可达?为什么§10.4/(3.2)或§10.4/(3.3)不适用于它们?

sr4lhrrt

sr4lhrrt1#

根据规则10.4.3.2,N::f是从use_f声明可访问。
在确定N::g是否可从use_g到达时,我们发现10.4.3.2和10.4.3.3都不适用。

  • 10.4.3.2不适用,因为g((T(), x))是一个依赖调用,因此在声明模板use_g时,还不能确定哪个函数实际上是由该调用命名的。(将确定何时示例化use_g,但在该情况下,它可能仅暗示N::g可从use_g的特定专门化到达,而不是模板use_g本身。)
  • 10.4.3.3指导我们考虑一个对g的假设调用,其中每个依赖于类型的参数都被替换为一个没有关联命名空间或实体的类型表达式。因此,例如,我们可以用0替换(T(), x),给出假设调用g(0)。这在名称查找阶段将找不到N::g,所以它不会使N::g声明可达。

出于类似的原因,N::h不能从use_h声明可达。
当示例化use_h<int>时,则应用规则10.4.3.2。此时,编译器确定(T(), x)的类型为N::X,并实际执行h的名称查找,通过依赖于参数的查找来查找N::h。即,h((T(), x))将函数命名为这个特定专门化中的N::h(其中T = int),而不是原始模板中的函数。

相关问题