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

具有未使用模板参数的函数模板

  •  11
  • olist  · 技术社区  · 7 年前
    template<typename T>
    struct a 
    { 
      using type = int;
      typename T::type i;
    };
    
    template<typename T, typename = a<T>>
    void f1(T) {}
    
    template<typename T, typename = typename a<T>::type>
    void f2(T) {}
    
    int main()
    {
      f1<int>(1); // ok
      f2<int>(1); // error
    
      return 0;
    }
    

    实例化 a<int> 应该是个错误,因为 int::type 是非法的。但看起来 f1<int> 无法导致 a<T> 但是 f2<int> 罐头。原因是什么?

    1 回复  |  直到 7 年前
        1
  •  15
  •   songyuanyao    7 年前

    当类型用作 template argument (包括默认模板参数),它不需要是完整类型。

    类型模板参数的模板参数必须是类型ID,它可以命名不完整的类型:

    所以 f1 ,默认模板参数为 a<T> 也不一定要完整。鉴于 f1<int>(1); a<int> 不需要实例化。

    但是当您将类模板的成员作为默认模板参数引用时 typename a<T>::type 属于 f2 , A & T;T & GT; 必须是完整类型,然后导致 implicit instantiation

    当代码引用上下文中需要完全定义类型的模板时,或者当类型的完整性影响代码时,并且此特定类型尚未显式实例化,则会发生隐式实例化。例如,当构造此类型的对象时,而不是构造指向此类型的指针时。

    这适用于类模板的成员:除非该成员在程序中使用,否则它不会被实例化,也不需要定义。

    因此给出 f2<int>(1); , a & lt;int & gt; 将被实例化,然后导致编译错误。