成员变量中的类模板参数扣除

Class Template Argument Deduction in member variables

本文关键字:参数 变量 成员      更新时间:2023-10-16

在此处展开版本。

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

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

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

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

但它使实施代码复杂化,根本不是优雅。

不,这不是错误。这是因为可能有不同的构造函数要求相同的成员变量(通过类的构造器init列表来称呼),可能会产生不同的扣除结果。

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