是否可以定义一个使用默认值的通用引用的构造函数?



当我试图定义一个使用默认值作为参数的通用引用的构造函数时,如下所示:

struct S {
int x; // I know that universal ref is useless for int, but it's here for simplicity
template<class T>
S(const T&& arg = 123) : x(std::forward(arg)) { }

// S(const auto&& arg = 123) : x(std::forward(arg)) { }
// The auto-syntax fails as well, yields similar error
};
int main() {
S s;
}

我得到一个错误:

<source>:18:7: error: no matching constructor for initialization of 'S'
S s;
^
<source>:10:5: note: candidate template ignored: couldn't infer template argument 'T'
S(const T&& arg = 123) : x(std::forward(arg)) { }
^
<source>:3:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
struct S {
^
<source>:3:8: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided

是否有一种方法可以用通用引用来做,或者我必须用另一种方式来做?

您仍然需要为模板形参指定一个默认实参。它不会从函数形参的默认实参中推导出来:

template<class T = int>

你也在滥用std::forward。它总是需要一个类型模板实参,该实参应该是由实参命名的转发引用中使用的模板形参。

x(std::forward<T>(arg))

最后,const右值引用几乎没有意义。特别是,它不形成转发引用。移除const:

S(T&& arg = 123)

那么它应该可以编译。但是,仅仅声明一个不带参数的额外重载可能会更简单。


注:在上述转发引用与问题所指的通用引用同义。前者是现在标准中使用的技术上正确的术语。后者更古老,在没有正式术语之前就在书面中普及了。

T不是从默认参数推导出来的,您也可以默认它:

template<class T = int>
S(T&& arg = 123) : x(std::forward<T>(arg)) {}

演示

最新更新