C++ 当模板具有默认参数时,忽略尖括号
假设我们有一个带有默认模板参数的类模板:C++ 当模板具有默认参数时,忽略尖括号,c++,templates,language-lawyer,c++17,C++,Templates,Language Lawyer,C++17,假设我们有一个带有默认模板参数的类模板: template <typename T = int> class Foo {}; 但它使实现代码复杂化,一点也不优雅 这被认为是标准中的错误吗 没有 模板是一个命名的构造,它基于一组参数生成另一个构造(类/函数/变量)。模板的名称不是它生成的构造的名称。模板的名称就是模板的名称;要命名模板生成的内容,必须提供模板参数 Foo是模板的名称Foo是由该模板及其关联模板参数生成的类的名称 P>有两个地方,其中C++允许模板以这样的方式使用,其
template <typename T = int>
class Foo {};
但它使实现代码复杂化,一点也不优雅 这被认为是标准中的错误吗 没有 模板是一个命名的构造,它基于一组参数生成另一个构造(类/函数/变量)。模板的名称不是它生成的构造的名称。模板的名称就是模板的名称;要命名模板生成的内容,必须提供模板参数
Foo
是模板的名称Foo
是由该模板及其关联模板参数生成的类的名称
<> P>有两个地方,其中C++允许模板以这样的方式使用,其参数是从表达式序列推导出来的。但这些都是非常特殊的地方,是为了方便而创建的。它们的存在并不是为了隐藏名称代表模板而不是生成的构造这一事实
有没有解决这个问题的建议
没有损坏的东西需要修理。目前还没有以这种方式增加变化的提案
省略尖括号是否存在实际问题
定义“实际问题”。从理论上讲,是否有可能对语言进行修改,以便在模板的所有参数均为默认值的情况下,可以在没有模板参数的情况下使用模板的名称来同时表示模板和模板生成的内容
这是可能的。但要具体说明会很复杂。你需要一位严肃的医生,一个能在深层次理解C++语法的人,以确定它是否可能,以及究竟需要做些什么来改变它。
但归根结底,它只对一小部分精选模板有用:所有参数都有默认值的模板。真正的问题是,这是否是一个足够普遍的案例,值得付出努力
这被认为是标准中的错误吗
没有
模板是一个命名的构造,它基于一组参数生成另一个构造(类/函数/变量)。模板的名称不是它生成的构造的名称。模板的名称就是模板的名称;要命名模板生成的内容,必须提供模板参数
Foo
是模板的名称Foo
是由该模板及其关联模板参数生成的类的名称
<> P>有两个地方,其中C++允许模板以这样的方式使用,其参数是从表达式序列推导出来的。但这些都是非常特殊的地方,是为了方便而创建的。它们的存在并不是为了隐藏名称代表模板而不是生成的构造这一事实
有没有解决这个问题的建议
没有损坏的东西需要修理。目前还没有以这种方式增加变化的提案
省略尖括号是否存在实际问题
定义“实际问题”。从理论上讲,是否有可能对语言进行修改,以便在模板的所有参数均为默认值的情况下,可以在没有模板参数的情况下使用模板的名称来同时表示模板和模板生成的内容
这是可能的。但要具体说明会很复杂。你需要一位严肃的医生,一个能在深层次理解C++语法的人,以确定它是否可能,以及究竟需要做些什么来改变它。
但归根结底,它只对一小部分精选模板有用:所有参数都有默认值的模板。真正的问题是,这是否是一个普通的情况值得付出努力。 < P>我不认为自己是一个语言专家,但我的立场是,你的提议试图解决的问题以同样的方式解决得更简单——“代码> STD::(Basic))字符串< /C> >。< /P> 我们有
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> class basic_string;
模板<
课程表,
类别特征=标准::字符特征,
类分配器=std::分配器
>类基本字符串;
然后是一组用于“非专家”用户的typedef
s,例如std::string
用于std::basic_string
如果专家用户希望使用其他模板参数,他们可以自己定义一个类型别名,这与上面的内容很好且一致。此外,这将模板与从中创建的类型清晰地分开
您建议允许所有参数的默认模板仅由MyTemplate
命名,而不是要求MyTemplate
,或使用使用MyTemplate=MyBasicTemplate代码>,存在以下问题:
- 它使语言的语法和规范复杂化。您需要接触问题中提到的所有上下文的允许语法,添加在需要类型名称的地方使用模板名称的功能,但前提是相关模板具有所有模板参数的默认值。如果你不改变所有这些,你会引入奇怪的不一致行为
- 您的建议和CTAD之间有一些重叠,但CTAD显然是为了减少初始化时的类型冗余。CTAD在其范围内提供了极大的舒适性,并且可以通过演绎指南进行扩展,而您的提案的语法糖分仅在一个很小的使用范围内相关,其好处要小得多
- 存在意外使用错误模板参数的危险(您是指默认模板参数还是忘记指定所需的模板参数?)。即使那是不可能的
struct S
{
Foo a; // Deduce Foo<int>
};
Foo* ptr; // Foo<int>*
Foo& ref; // Foo<int>&
int Foo::* mem_ptr; // int Foo<int>::*
std::function<Foo(const Foo&)> fn; // std::function<Foo<int>(const Foo<int>&)>
Foo Bar(const Foo&); // Foo<int> (*)(const Foo<int>&)
template <typename T = int>
class BasicFoo {};
using Foo = BasicFoo<>;
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> class basic_string;