§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)不适用于他们?
N::f
是decl-reachable fromuse_f
,由于规则10.4.3.2.
在确定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
decl可达。
由于类似的原因,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
),而不是在原始模板中。