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

时间:2018-10-12 09:26:42

标签: c++ templates language-lawyer c++17

编辑:
显然,GCC允许实例化没有参数列表(默认情况下为参数列表)的类模板,该列表不符合标准(符合Clang)。
我猜测要求使用方括号(即使参数列表为空)的原因是要明确表明它是模板实例化,而不是实际类型。
因此,我将最初的问题引向类模板和函数模板用例之间的区别:为什么在第二个代码段中,与第一个代码段中的A实例化相比,它允许调用不带括号的a?为什么不允许b?


原文:
可以实例化仅具有默认参数的类模板,而无需任何参数列表(请参见下面的A)。
但是,如果通过使用声明将该类模板的别名定义为具有相同默认参数的模板(请参见下面的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)中存在细微差别:如果在{的定义中指定了返回类型,则不需要参数列表{1}}。我想我理解原因,但是我欢迎您提供一些见解。否则,这两种情况都类似于类模板的情况。

a

Live on Coliru

而且,现代C ++标准(C ++ 11到C ++ 20)之间有显着差异吗?我对C ++ 17案例最感兴趣,但是我很想知道这些事情是否已经改变或将会改变。
据我所知,在C ++ 14中,类模板实例化始终需要一个参数列表,而函数模板调用则不需要。而且我还没有发现带有GCC的C ++ 17和C ++ 2a之间的区别。

1 个答案:

答案 0 :(得分:5)

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

  

使用模板参数包或默认模板参数时,模板参数列表可以为空。 在这种情况下,空的<>括号仍应用作模板参数列表

第1.7.3 / 4节中的C ++ 17措辞与第14.3 / 4节中的C ++ 14和C ++ 11措辞相同。

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

  

如果可以推导出所有模板参数,则可以全部省略;在这种情况下,空模板参数列表<>本身也可以省略。

第17.8.1 / 3节中的C ++ 17措辞与第14.8.1 / 3节中的C ++ 14和C ++ 11措辞相同。


您的

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

是一个变量模板,对于该模板不会进行任何参数推导。

相关问题