using-declaration和instantiation中的默认模板参数

Nel*_*eal 4 c++ templates language-lawyer c++17

编辑:
显然,GCC允许实例化没有参数列表的类模板(当参数默认时),这是不合规的(Clang是合规的).
我猜测要求括号的原因(即使参数列表为空)是明确表示它是模板实例化,而不是实际类型.
因此,我正在将我原来的问题转向类模板和函数模板案例之间的差异:为什么在第二个片段中允许调用无括号,与第一个片段中A的实例化相反?为什么不允许b?


原始:
只有默认参数的类模板可以在没有任何参数列表的情况下实例化(参见下面的A).
但是,如果通过using-declaration定义该类模板的别名作为具有相同默认参数的模板(参见下面的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;
}
Run Code Online (Sandbox Code Playgroud)

住在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();
}
Run Code Online (Sandbox Code Playgroud)

住在Coliru

另外,现代C++标准(C++ 11到C++ 20)之间是否存在显着差异?我最感兴趣的是C++ 17案例,但我很想知道这些事情是否已经改变,或者是否会发生.
从我所看到的,在C++ 14中,类模板实例化无论如何都需要参数列表,而函数模板调用则不需要.我没有发现C++ 17和C++ 2a与GCC之间存在差异.

Swo*_*ish 5

模板参数[temp.arg]/4(§12.3/ 4)

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

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

显式模板参数规范[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>;
Run Code Online (Sandbox Code Playgroud)

是一个变量模板,不会发生参数推断.