当我试图定义一个使用默认值作为参数的通用引用的构造函数时,如下所示:
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)) {}
演示