模板专门化在其实例化点上看不到功能 [英] Template specialization doesn't see a function in its point of instantiation

查看:91
本文介绍了模板专门化在其实例化点上看不到功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么它不正确

I don't understand why it isn't correct

#include <iostream>
using namespace std;

struct CL{};

template <typename T>
void fnc(T t)
{
    f(t);
}

namespace NS {
    void f(CL){}
    void fn() {fnc(CL()); /*error is here*/}
    //point of instantiation fnc<CL> is here (in namespace scope,
    //according to 14.6.4.1/1)
}

int main(){}

在模板函数fnc中调用f(t)取决于模板参数,然后名称查找必须在实例化点.我看到了Standard(C ++ 14)14.6.4.1/1

Calling f(t) in template function fnc is dependent on template parameter and then name lookup must be at an instantiation point. I saw Standard (C++ 14) 14.6.4.1/1

对于功能模板专业化,成员函数模板 专门化,或成员函数或静态的专门化 类模板的数据成员,如果专门化是隐式的 实例化,因为它是从另一个模板中引用的 专业化及其引用的上下文取决于 在模板参数上,实例化的点 专业化是封闭的实例化点 专业化. 否则,这种情况的实例化点 专门化紧跟在名称空间作用域声明之后,或 专门化的定义.

For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.

f(CL)fnc<CL>的实例化点是可见的,但是所有编译器(VS,gcc,clang)都给出错误.发生这种行为的原因是什么?

f(CL) is visible at a point of instantiation of fnc<CL>, but all the compilers (VS, gcc, clang) give an error. What is reason for that behavior?

推荐答案

此处fnc的参数t是从属名称,在解析模板时无法解析.而是在实例化点再次查找它们.这就是所谓的两阶段查找:第一阶段是模板的解析,第二阶段是模板的实例化.

Here the argument t of fnc is a dependent name, which cannot be resolved when parsing templates. Instead, they are looked up again at the point of instantiation. This is so-called two-phase lookup: the 1st phase is the parsing of a template, and the 2nd phase is its instantiation.

您的问题的答案在于,在POI(实例化点)执行的第二次查询仅是 ADL .由于未在与void f(CL)相同的名称空间中定义struct CL,因此POI查找将不会发生,也不会找到它.

The answer to your question lies in the fact that the 2nd lookup performed at the POI (point of instantiation) is only an ADL. Because the struct CL is not defined inside the same namespace with void f(CL), the POI lookup would therefore not take place and would not find it.

如果您尝试将结构CL的定义放入名称空间中,以使 ADL 生效,它将很好地编译.

If you try to put the definition of the struct CL into the namespace to make ADL take effect, it will compile well.

namespace NS {
    struct CL{};
    void f(CL){}
    //...
}

根据不合格名称查找的规则,(由我粗体显示)

According to the rule of unqualified name lookup, (bold by me)

对于模板定义中使用的从属名称,查找为 推迟到知道模板参数为止,这时ADL 检查具有外部链接的函数声明(直到C ++ 11) 从模板定义上下文以及在 模板实例化上下文,而非ADL查找仅检查 具有外部链接的函数声明(直到C ++ 11)是 在模板定义上下文中可见(换句话说,添加 模板定义后没有新的函数声明 可见,除了通过ADL ).

For a dependent name used in a template definition, the lookup is postponed until the template arguments are known, at which time ADL examines function declarations with external linkage (until C++11) that are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declarations with external linkage (until C++11) that are visible from the template definition context (in other words, adding a new function declaration after template definition does not make it visible except via ADL).

这篇关于模板专门化在其实例化点上看不到功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆