代码之家  ›  专栏  ›  技术社区  ›  felix

为什么即使直到最后才定义实际类型,依赖名称也可以被认为是完整的

  •  9
  • felix  · 技术社区  · 7 年前

    Consider this example

    template <class T>
    void Yeap(T);
    
    int main() {
        Yeap(0);
        return 0;
    }
    
    template <class T>
    void YeapImpl();
    
    struct X;
    
    template <class T>
    void Yeap(T) {
        YeapImpl<X>(); // pass X to another template
    }
    
    template <class T>
    void YeapImpl() {
        T().foo();
    }
    
    struct X {
        void foo() {}
    };
    

    struct X 直到最后才被定义。我曾经相信,所有odr使用的名称在实例化时都必须是完整的。但是在这里,编译器如何在定义它之前将它视为一个完整的类型呢?

    我在cppreference中检查了依赖名称和函数模板实例化的绑定规则和查找规则,但是没有一个能够解释这里发生的事情。

    1 回复  |  直到 7 年前
        1
  •  8
  •   Barry    7 年前

    [temp.point]/8 阅读,编辑不相关的部分:

    YeapImpl<X> 有两个实例化点:在问题的注释行和翻译单元的末尾调用。在第一个实例化点, X 是不完整的,这会使函数体的形式不正确。在实例化的第二点中,

    这两个专业有[非常]不同的含义。