C++ 成员变量中的类模板参数推断

C++ 成员变量中的类模板参数推断,c++,templates,c++17,C++,Templates,C++17,扩展版 我们可以创建具有默认模板参数的类模板对象,而无需键入尖括号: int main() { std::less a; } 但对于成员变量,我们不能这样做: struct S { std::less a; // I want only type std::less<void> here }; 但它使实现代码复杂化,一点也不优雅。不,它不是一个bug。这是因为可能有不同的构造函数为同一个成员变量调用(通过类的构造函数init list调用),可能会产生不同的推断结

扩展版

我们可以创建具有默认模板参数的类模板对象,而无需键入尖括号:

int main()
{
    std::less a;
}
但对于成员变量,我们不能这样做:

struct S
{
    std::less a; // I want only type std::less<void> here
};

但它使实现代码复杂化,一点也不优雅。

不,它不是一个bug。这是因为可能有不同的构造函数为同一个成员变量调用(通过类的构造函数init list调用),可能会产生不同的推断结果


为了防止潜在的冲突,您必须为非静态成员提供模板参数。(静态成员不是问题,因为将有一个单一的构造函数调用它们)

事实上,不能在成员变量中使用
auto
。语法相同并不意味着它是相同的。第一个是变量声明,另一个是字段声明。对于那些想知道CTAD是什么意思的人:。@Lyberta:“现在对于其他99%,我想隐藏Foo实际上是一个类模板的事实”嗯,你不能;C++不允许你。即使CTAD在这里起作用,一般来说也不会起作用。您不能有一个将
Foo
作为参数的函数。您不能与
Foo
的静态成员交谈,也不能从中获取成员指针。CTAD并不是为了隐藏某些东西是模板这一事实。这是一个方便的功能,允许编译器找出它已经知道的内容。@Lyberta:你的问题是关于成员变量中的CTAD。我是在回答一个附带问题:事实上,您希望在成员变量中使用CTAD的原因永远不会解决,即使您可以在成员变量中使用CTAD。因此,这样的“答案”无法回答您提出的问题。由于其他人都已经根据成员变量中的CTAD问题回答了问题,所以你改变这个问题是不公平的。没有现成的初始值设定项,所以在我看来,即使在调用构造函数之前,类型也是固定的。@Lyberta这是什么意思?正如我试图解释的,对于同一个成员变量,可能会有不同的构造函数调用。你希望CTAD规则如何运作?我不明白你现在在问什么。如果没有CTAD,
std::less
是一个模板,因此必须使用它<代码>标准::小于a将非常好地工作。@Lyberta:“但它暴露了它的模板性,这并不总是令人满意的。”它是一个模板;这是一个将向用户公开的事实。CTAD并不是要隐藏某些东西是模板这一事实;这是一个方便的功能,可以防止人们重新键入相同的信息。@Lyberta,因为这不是一个解决办法<代码>std::less将始终是一个模板。CTAD(本质上)是一种类型辅助工具,它允许人们不重复相同的信息两次——对于构造函数调用和模板参数。我也不喜欢你的问题随着时间的推移而演变,现在它变成了一个完全不同的问题,
template <typename T = int>
class Foo {};
template <typename T = int>
class BasicFoo {};

using Foo = BasicFoo<>;