成员变量中的类模板参数推导

3 c++ templates c++17

扩展版在这里

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

int main()
{
    std::less a;
}
Run Code Online (Sandbox Code Playgroud)

但是对于成员变量我们不能这样做:

struct S
{
    std::less a; // I want only type std::less<void> here
};
Run Code Online (Sandbox Code Playgroud)

看起来第一种情况由于CTAD起作用,但为什么编译器不能std::less<void>在第二种情况下推断?也许我们不应该在那里应用 CTAD,而是提供不同的机制。

这是否被认为是标准中的错误?有没有修复它的建议?

我的用例:

我有一个提供默认参数的类模板,如下所示:

template <typename T = int>
class Foo {};
Run Code Online (Sandbox Code Playgroud)

模板参数是我自己从未使用过的专家专用功能,但它适用于那些想要完全灵活性的 1% 的专家。现在对于其他 99% 我想隐藏Foo实际上是类模板但它不起作用的事实,因为用户在将Foo<>其声明为成员变量时必须键入,当前的解决方案是:

template <typename T = int>
class BasicFoo {};

using Foo = BasicFoo<>;
Run Code Online (Sandbox Code Playgroud)

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

Ser*_*eyA 7

不,这不是错误。这是因为同一个成员变量(通过类的构造函数初始化列表调用)可能会调用不同的构造函数,从而可能产生不同的推导结果。

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

  • @Lyberta:“*但它暴露了它的模板性,这并不总是可取的。*”它是一个模板;事实是*将暴露*给用户。CTAD 并不是要隐藏某些东西是模板的事实;这是一个方便的功能,可以让人们不必重新输入相同的信息。 (3认同)
  • @Lyberta 因为这不是解决方法。`std::less` 将永远是一个模板。CTAD(本质上)是一种打字辅助,它允许人们不会重复两次相同的信息——对于构造函数调用和模板参数。我也不喜欢你的问题随着时间的推移如何演变,现在它变成了一个完全不同的问题, (2认同)