【问题标题】:C++17 Default template arguments: invalid use of template-name without an argument listC++17 默认模板参数:在没有参数列表的情况下无效使用模板名称
【发布时间】:2020-01-14 18:19:34
【问题描述】:

使用 C++17,您可以在 main 中进行类模板参数推导,如下例所示:

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 myX 的情况下无效使用模板名称“X”;

【问题讨论】:

  • 不是关于 CTAD,但有些论点是相似的:auto-type members
  • 你的例子并没有,呃,推断出任何东西。如果只想使用默认模板参数,写X&lt;&gt;?

标签: c++ templates c++17


【解决方案1】:

我没有参与该决定,但是,我确实看到在允许它时存在一些问题。让我们假设以下代码:

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} {}

在这种情况下,我们是否期望 myX 为 X&lt;int&gt; 或 X&lt;double&gt; 或 X&lt;char&gt;?

我可以看到对此可能存在混淆。由于标准委员会无法恢复其决定,因此最好采取确定的一小步,看看人们是否需要它以及他们期望发生什么。

【讨论】:

  • 特别是如果构造函数的实现不在头文件中而是在 cpp 文件中,cpp 文件中的代码会影响头文件中成员的类型。这不适用于 C++ 的编译和链接方式(出于同样的原因,我们也必须将模板化函数的定义放在头文件中)。
  • 这个例子并不需要一个单独的文件,即使是一个内联的Y() : myX{0.0} {} 也很能说明问题。
  • 关于人们是否需要它,这里有一个我觉得很方便的例子:假设我们有一个(非模板化的)类 Z 和 1000 个具有 Z 成员的其他类。在某些时候,我们决定将 Z 更改为模板类。我会指定适当的默认模板,但是如果我不想更改类的名称,则需要在 1000 个类的 Z 成员中放置一个 ,这不太好。可能还有更重要的用例。也许有一套很好的规则可以体现在未来的 C++ 版本中,例如您的答案中的情况。
  • using Z = ZTemplate&lt;&gt;;?
  • 感谢您的建议,但我也看到了它的缺点,这就是我写“如果我不想更改班级名称”的原因。使用using Z = ZTemplate&lt;&gt; ,我们将有两个不同的名称:需要默认模板的类将具有类型为 Z 的成员,这很好,但其他类的成员类型为ZTemplate&lt;something&gt; 而不是Z&lt;something&gt;,这在imo 中会更好。
猜你喜欢
  • 1970-01-01
  • 2021-12-23
  • 2018-10-12
  • 2013-08-13
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
  • 1970-01-01
相关资源
最近更新 更多