当目标与数组聚合时,完美转发失败
Perfect forwarding fails when target is aggregate with array
#include <iostream>
struct X2
{
int i;
int j;
char buf[10];
};
X2 glob{1,2,"abc"}; // OK
struct X
{
X2 x2;
template<typename... Args>
X(Args&&... args): x2{args...} {}
};
int main()
{
X x; // OK
X y{1, 2}; // OK
X z{1, 2, "abc"}; // error
}
最后一行给出错误:17 : error: invalid conversion from 'const char*' to 'char' [-fpermissive]
如果我使用 std::forward(args)...
而不是 args...
那么会出现更多错误;如果我尝试使用 {'a', 'b', 'c', ' '}
作为初始值设定项而不是字符串文字,也会出错。
有没有办法使这项工作,即允许X z{......};
接受大括号内的任何内容,这些内容将成为x2
的法定初始值设定项,并且实际上确实初始化了x2
?
这是一个从 C++98 继承而来的不稳定的设计问题:某些转换或初始化在语法上仅限于文字,特别是字符串文字作为字符数组的初始值设定项 ([dcl.init.string]/1( 和整数文字作为空指针常量 ([conv.ptr]/1(。当然,这与"完美"转发并不相符。
对于空指针,通过引入 nullptr
来规避该问题,可以使用它代替0
,即使在转发后也能正常工作。
在您的情况下,基本上有两个主要选项:
-
利用大括号省略 -
X
也是一个聚合:struct X { X2 x2; } z{1, 2, "abc"}; // Ok
-
声明
buf
具有类类型,例如std::string
,或者,也许更适合您的情况,一些静态大小的等效项(限制为大小 10(。
相关文章:
- 将函数参数完美转发到函数指针:按值传递呢?
- C++20理念:要求表达和完美转发
- 我可以列表初始化 std::vector 并完美转发元素吗?
- 返回值的完美转发?
- 使用衰减与完美转发
- 可变参数模板:将整数参数完美转发到 lambda
- 完美转发C++重载和模板化函子及其参数
- 在完美转发中需要衰减
- C++完美转发:如何避免悬空引用
- 无法理解一段具有完美转发和省略号的C++代码
- 在编写包装现有函数并检查错误的模板函数时,如何使用完美转发?
- 完美转发可变参数模板模板
- 在完美转发函数中公开参数类型,避免代码重复
- 使用完美转发的模板转换构造函数
- 完美转发使用结构化绑定声明的变量
- 完美转发常量参数以进行持续评估
- 使用auto&&完美转发返回值
- 完美转发可变参数模板参数到成员函数
- 无需使用 ODR 即可实现完美转发
- 使用模板类完美转发