【问题标题】:Default template parameters in using-declaration and instantiation使用声明和实例化中的默认模板参数
【发布时间】:2018-10-12 09:26:42
【问题描述】:

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


原文:
一个只有默认参数的类模板可以在没有任何参数列表的情况下实例化(参见下面的 A)。
但是,如果该类模板的别名通过 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)略有不同:如果在@的定义中指定了返回类型,则不需要参数列表987654325@。我想我明白为什么,但我欢迎一些见解。否则,这两种情况都类似于类模板的情况。

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++ 标准(C++11 到 C++20)之间是否存在显着差异?我最感兴趣的是 C++17 案例,但我很想知道这些事情是否已经改变,或者将会改变。
据我所知,在 C++14 中,类模板实例化无论如何都需要参数列表,而函数模板调用则不需要。而且我还没有发现 C++17 和 C++2a 与 GCC 之间的区别。

【问题讨论】:

  • Coliru 使用了一个稍微过时的clang(5.0.0,最新版本是7.0.0),它没有实现一些关于CTAD的缺陷报告。
  • @cpplearner 我不太明白这应该影响哪一部分。 Clang 似乎符合我的要求?
  • 哪个clang、clang 5.0.0或clang 7.0.0(允许A a;)?
  • @cpplearner 哦,所以 Clang 7.0.0 允许和 GCC 一样,不合规?这只是两个编译器为了方便而添加的东西,还是两者都有错误?还是实际上应该被标准允许?

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


【解决方案1】:

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

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

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

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

如果所有的模板参数都可以推导出来,它们都可以被省略;在这种情况下,空模板参数列表&lt;&gt; 本身也可以省略。

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


你的

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

是一个变量模板,不会发生参数推导。

【讨论】:

  • 那么这是允许省略括号的 GCC“错误”吗?函数模板案例呢?
  • 好吧,它看起来确实像 GCC 的一个错误,因为 Clang 不允许在类模板案例中使用它。不过,它适用于功能模板。有什么理由造成这种差异?
  • 也许添加另一个简单的例子来说明clang允许什么,你担心你的问题?顺便提一句。你知道auto c = a&lt;&gt;; 定义了一个函数指针a?
  • 我知道 c 是一个函数指针(和 b 一样)。有没有更接近函数别名的东西?
  • @Nelfeal 不是。只是要求确定。不过,您的 b 是一个变量模板。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多