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

使用声明和实例化时的默认模板参数

  •  3
  • Nelfeal  · 技术社区  · 6 年前

    编辑:
    显然,GCC允许实例化一个没有参数列表的类模板(当参数是默认值时),这是不兼容的(Clang是兼容的)。
    我猜之所以需要方括号(即使参数列表是空的)是为了明确它是一个模板实例化,而不是一个实际的类型。
    因此,我将我最初的问题转向类模板和函数模板案例之间的差异:为什么在第二个代码段中,它允许调用没有括号的a,而不是在第一个代码段中实例化a?为什么不允许b?




    但是,如果通过using声明将该类模板的别名定义为具有相同默认参数的模板(请参见下面的B),则其实例化需要参数列表(可能为空)。
    类似地,将类模板的别名定义为实际类型(参见下面的C)需要一个参数列表(同样,可能是空的)。
    这背后有什么原因吗?
    template<int i = 1>
    struct A {
        operator int() { return i; }
    };
    
    template<int i = 2>
    using B = A<i>;
    
    // using C = A;    <-- error: missing template arguments after 'A'
    using C = A<>;
    
    int main() {
        A a; // Edit: Actually should require brackets: A<> a;
        // B b;    <-- error: missing template arguments before 'b'
        B<> b;
        C c;
    }
    

    Live on Coliru

    我尝试过用函数模板而不是类模板构建一个类似的场景,在最后一种情况(C)中有一点不同:如果在的定义中指定了返回类型,则不需要参数列表 a . 我想我明白为什么,但我希望能有一些见解。否则,这两种情况与类模板类似。

    template<int i = 1>
    auto a() { return i; }
    // auto a() -> int { return i; }
    // if the return type is specified, c can be defined as commented below
    
    template<int i = 2>
    auto b = a<i>;
    
    // auto c = a;    <-- error: unable to deduce 'auto' from 'a'
    auto c = a<>;
    
    int main() {
        a();
        // b();    <-- error: missing template arguments before '(' token
        b<>();
        c();
    }
    

    Live on Coliru


    从我所看到的,在C++ 14中,类模板实例化需要参数列表,而函数模板调用不需要参数列表。我还没有发现C++ 17和C++ 2a与GCC的区别。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Swordfish    6 年前

    Template arguments [temp.arg]/4 (§12.3/4)

    模板参数列表 可以为空。 在这种情况下,空的 <> 支架仍应用作 模板参数列表

    C++ 17中的相同措辞§173/4,对于C++ 14和C++ 11§14.3/4.

    Explicit template argument specification [temp.arg.explicit] (§12.9.1/3)

    如果所有的模板参数都可以推导出来,那么它们都可以省略;在本例中,空模板参数列表 <>

    C++ 17中的相同措辞§1.81/3,对于C++ 14和C++ 11§14.8.1/3.


    你的

    template<int i = 2>
    auto b = a<i>;
    

    变量模板 不会进行任何参数推导。