Why is <> required when specifying a template class which has defaults for all its template parameters?

一笑奈何 提交于 2019-12-08 18:58:36

问题


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

e.g.

#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.

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?


回答1:


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>&&);

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>.

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

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-seqoptinitializer

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

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.


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.



来源:https://stackoverflow.com/questions/42670137/why-is-required-when-specifying-a-template-class-which-has-defaults-for-all-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!