C++17默认模板参数:在没有参数列表的情况下无效使用模板名称。

8

在 C++17 中,您可以像以下示例中一样在主函数中进行类模板参数推导:

template<class T = int>
struct X{};

int main()
{
    X myX;
}

为什么无法为数据成员进行模板参数推导?
template<class T = int>
struct X{};

struct Y
{
   X myX;
};

int main()
{
   Y myY;
}

错误: 在没有参数列表的情况下无效使用模板名称'X' X myX;


不是关于CTAD的,但其中一些参数相似:自动类型成员 - Barry
你的例子并没有推导出任何东西。如果你只想使用默认的模板参数,只需写X<>即可。 - Davis Herring
1个回答

8

我并没有参与决策,但是我认为允许这样做存在一些问题。我们假设以下代码:

template<class T = int>
struct X
{
    X(T t = T{}) {}
};

这样做可以使您的变量仍然正常:
int main()
{
     Y myY;
}

然而,如果Y有一个在另一个文件中实现的构造函数呢?
struct Y
{
    Y();
    X myX{'a'};
};

Y::Y() : myX{0.0} {}

在这种情况下,我们是否期望myXX<int>, X<double>还是X<char>
我可以看出这可能会引起混淆。由于标准委员会无法撤销其决定,最好采取一个确定的小步骤,并查看人们是否需要它以及他们希望发生什么。

特别是当构造函数的实现不在头文件中而在cpp文件中时,cpp文件中的代码会影响头文件中成员的类型。这种方式无法与C++编译和链接的方式兼容(出于与模板函数定义必须放在头文件中相同的原因)。 - n314159
不需要为那个例子单独创建一个文件,甚至一个内联的 Y() : myX{0.0} {} 就足够具有说明性了。 - Barry
关于人们是否需要它,这里有一个例子,我会发现它很方便:假设我们有一个(非模板化)类Z和1000个其他类,它们都有一个Z成员。在某些时候,我们决定将Z更改为模板类。我将指定适当的默认模板,但如果我不想更改类的名称,我将需要在1000个类的Z成员中放置<>,这并不好看。可能还有更重要的用例。也许有一套好的规则可以体现在未来的C++版本中,针对像您回答中的情况。 - dcon
使用 Z = ZTemplate<>; - JVApen
谢谢您的建议,但我也看到了一个缺点,这就是为什么我写了“如果我不想改变类的名称”。使用 using Z = ZTemplate<> 我们将有两个不同的名称:需要默认模板的类将具有类型为 Z 的成员,这很好,但其他类将具有类型为 ZTemplate<something> 而不是 Z<something> 的成员,我认为后者更好。 - dcon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接