模板实例化时非限定名查找为何不纳入调用函数名?
为何模板实例化时非限定名查找不考虑调用函数的名称?
为何模板实例化过程中的非限定名查找不会考虑调用函数的名称?具体而言,以下两个示例中的static_assert均失败,恳请解释原因。
示例1:简单非成员函数
template <typename T> inline constexpr bool has_foo = requires(T& t) { foo(t); }; void foo(int x) { static_assert(has_foo<int>); } int main() { foo(42); }
示例2:非成员模板函数
template <typename T> inline constexpr bool has_foo = requires(T& t) { foo(t); }; void foo(auto x) { static_assert(has_foo<decltype(x)>); } int main() { foo(42); }
核心原因:非限定名查找的作用域规则与模板实例化的时机
这两个例子的问题根源在于模板中非限定名的查找规则:模板里的非限定名,只会查找模板定义点处可见的实体,完全不考虑模板实例化点的作用域内容。
具体拆解:
has_foo<T>是全局作用域下定义的模板变量,它的requires表达式里用到了非限定名foo。在模板定义的位置(全局作用域),后面那个foo函数不管是普通函数还是模板函数,都还没被声明,所以此时foo是未定义的名字。- 当我们在
foo函数内部实例化has_foo时,虽然实例化点在foo函数里,但非限定名查找不会“回头”找这个实例化点所在的foo函数——函数的作用域是它自己的内部代码,和模板定义的全局作用域是平行的,实例化点的函数名称不会被纳入模板定义点的查找范围。
简单说就是:模板写在哪,就只认那个位置能看到的名字,跟你后来在哪用这个模板、用的地方有没有同名函数没关系。
内容的提问来源于stack exchange,提问作者Oersted
相关产品推荐
相关产品推荐

