【发布时间】:2019-03-06 15:40:59
【问题描述】:
扩展版here.
我们可以创建具有默认模板参数的类模板对象,而无需键入尖括号:
int main()
{
std::less a;
}
但我们不能对成员变量这样做:
struct S
{
std::less a; // I want only type std::less<void> here
};
看起来第一种情况是由于CTAD,但为什么编译器不能在第二种情况下推断出std::less<void>?也许我们不应该在那里应用 CTAD,而是提供不同的机制。
这是否被视为标准中的错误?有解决方案吗?
我的用例:
我有一个提供默认参数的类模板,如下所示:
template <typename T = int>
class Foo {};
模板参数是我自己从未使用过的专家专用功能,但它适用于那些需要完全灵活性的 1% 的专家。现在对于其他 99% 的人,我想隐藏 Foo 实际上是一个类模板但它不起作用,因为用户在声明它为成员变量时必须键入 Foo<>,当前的解决方案是:
template <typename T = int>
class BasicFoo {};
using Foo = BasicFoo<>;
但它使实现代码复杂化,一点也不优雅。
【问题讨论】:
-
不能在成员变量中使用
auto这一事实。 -
只是语法相同并不意味着它是相同的东西。第一个是变量声明,另一个是字段声明。
-
对于那些想知道 CTAD 意味着什么的人:Class template argument deduction.
-
@Lyberta: "现在对于其他 99% 的人,我想隐藏 Foo 实际上是一个类模板的事实" 好吧,你不能; C++ 不允许你这样做。即使 CTAD 在这里工作,它也不会在一般情况下工作。您不能拥有将
Foo作为参数的函数。您不能与Foo的静态成员交谈或从中获取成员指针。 CTAD 不是为了隐藏某物是模板的事实。这是一个方便的功能,允许编译器找出它已经知道的内容。 -
@Lyberta:您的问题是关于成员变量中的 CTAD。我正在回答一个附带问题:即使您可以在成员变量中获得 CTAD,您想要 CTAD 在成员变量中的原因也永远不会成功。因此,这样的“答案”不会回答您提出的问题。而且由于其他人都已经根据成员变量中的 CTAD 问题进行了回答,因此您更改问题是不公平的。