代码之家  ›  专栏  ›  技术社区  ›  nyronium whaley

为什么函数模板不能访问前向声明的类型?

  •  0
  • nyronium whaley  · 技术社区  · 6 年前

    问题

    考虑一下这个代码( live version ),在这里我已经声明了 struct S Use 哪个ODR使用它。 S 之后 函数,但在任何 .

    struct S;
    
    template<typename T> void Use(S& s, const T& t) { // ODR-use S
        s.Use(t); // error: member access into incomplete type 'S'
    }
    
    struct S {
        template<typename T> void Use(const T&) { }
    };
    
    int main() {
        auto s = S{}; Use(s, 2); // Instantiation of Use<...>
    }
    

    这不会编译,因为显然,S的定义对 功能。

    理论基础

    基于我对函数模板的理解 §13.9.1 of the latest working draft 这不应该是个问题,因为当函数模板被实例化时,所有类型都被完全定义。

    不过,在我看来,所有依赖类型都可以访问实例化时可用的定义,而非依赖类型将使用函数定义中可用的版本。不幸的是,我在定义这种行为的标准中找不到相应的段落。

    解决问题

    为了解决这个问题,我可以使用IIFE“刷新”当前的定义:

    // This is OK:
    template<typename T> void Use(S& s, const T& t) {
        [&](auto& s_) { s_.Use(t); }(s);
    }
    

    // This is also OK:
    template<typename T, typename SS = S> void Use(SS& s, const T& t) {
        s.Use(t);
    }
    

    所以现在我想知道,为什么实例化的模板不总是能够访问任何类型的最新定义,而不仅仅是依赖类型?如上所示,您可以使用立即计算的lambda来强制编译器更新任何类型—那么为什么这不是自动完成的呢?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Jesper Juhl    6 年前

    forward声明只是向编译器保证“是的,我保证这种类型 真正地 需要