§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)不适用于它们?
1条答案
按热度按时间sr4lhrrt1#
根据规则10.4.3.2,
N::f
是从use_f
声明可访问。在确定
N::g
是否可从use_g
到达时,我们发现10.4.3.2和10.4.3.3都不适用。g((T(), x))
是一个依赖调用,因此在声明模板use_g
时,还不能确定哪个函数实际上是由该调用命名的。(将确定何时示例化use_g
,但在该情况下,它可能仅暗示N::g
可从use_g
的特定专门化到达,而不是模板use_g
本身。)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
),而不是原始模板中的函数。