为什么<>指定其所有模板参数均具有默认值的模板类时是否必需? [英] Why is <> required when specifying a template class which has defaults for all its template parameters?

查看:52
本文介绍了为什么<>指定其所有模板参数均具有默认值的模板类时是否必需?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在指定所有模板参数均具有默认值的模板类时,是否有充分的理由为什么需要<>

Is there a good reason why <> is required when specifying a template class which has defaults for all its template parameters?

例如

#include <iostream>

template<typename T = int>
class C {
public:
    T obj = 0;
};

int main()
{
    C c1; // Error on almost all compilers (see note below)
    C<> c2;
    std::cout << c1.obj << " " << c2.obj << std::endl;
    return 0;
}

一个例子的缺点是,如果您有一个已经使用过的类在各个地方,然后您将其重构为具有默认参数作为其模板参数的类模板,然后必须在所有使用以下位置的地方添加<>

An example disadvantage of this is that if you have a class which is already used in various places, and you later refactor it to be a class template with default parameters for its template arguments, then you have to add <> in all the places which use the class.

注意:它看起来像是GCC最新的HEAD(7.0.1)接受不带<> 的语法。早期版本没有,Clang的任何版本也没有。这是最新版GCC HEAD中的错误吗?还是C ++ 17的标准现在接受不带<> 的语法,而GCC就在这里?

Note: it looks like GCC latest HEAD (7.0.1) accepts the syntax without <>. Earlier versions do not and neither does any version of Clang. Is this a bug in the latest GCC HEAD? Or perhaps C++17's standard now accepts the syntax without <> and GCC is just ahead here?

推荐答案

在C ++ 17中,它格式正确:

In C++17, this is well formed:

C c1{};

由于类模板的推论。我们将为每个构造函数(和推导指南)合成一个函数并执行重载解析:

due to deduction for class templates. We'd synthesize a function for each constructor (and deduction guide) and perform overload resolution:

template <class T=int> C<T> foo();
template <class T=int> C<T> foo(C<T> const&);
template <class T=int> C<T> foo(C<T>&&);

第一个是可行的重载,而另外两个则不可行,因此扣除成功且占位符 C 被推导的类型 C< int> 代替。

The first one is a viable overload, and the other two are not, so deduction succeeds and the placeholder C is replaced by the deduced type C<int>.

但是,在语法上,[dcl.type.class.deduct]中需要

However, grammatically, an initializer is required in [dcl.type.class.deduct]:


如果推导类类型的占位符在简单声明 decl-specifier-seq 中显示为 decl-specifier ,则该声明的 init-declarator 的格式应为:

If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of a simple-declaration, the init-declarator of that declaration shall be of the form:

declarator-id attribute-specifier -seq opt 初始化器

占位符由以下所选函数的返回类型代替类
模板扣除的重载解析(13.3.1.8)。

The placeholder is replaced by the return type of the function selected by overload resolution for class template deduction (13.3.1.8).

但是 C c; 不包含初始化器,因此它在语法上不适合。这是允许的gcc错误。 显然,在Kona中取消了此限制,因此 C c; 在C ++中的格式确实正确17。一旦出现新的用语,我将更新答案。

But C c; contains no initializer, so it doesn't fit grammatically. This is a gcc bug for allowing this. Although it seems odd to disallow this specifically. Apparently, this restriction has been lifted in Kona, so C c; will indeed be well-formed in C++17. I will update the answer once new wording comes out.

在C ++ 17之前,该语句格式不正确仅仅是因为 C 不是一种类型。 C C< 不是一回事。对于所有默认模板参数,现在有,现在仍然没有特别考虑。类型和类模板是不同的,并且继续被区别对待。

Before C++17, the statement was ill-formed simply because C is not a type. C and C<> are not the same thing. There was, and still is no, special consideration for having all defaulted template parameters. Types and class templates are different, and continue to be treated differently.

这篇关于为什么&lt;&gt;指定其所有模板参数均具有默认值的模板类时是否必需?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆