当目标与数组聚合时,完美转发失败

时间:2015-12-19 05:11:13

标签: c++ aggregate c++14 perfect-forwarding

#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', '\0'}作为初始化程序而不是字符串文字,也会出错。

有没有办法让这项工作成功,即允许X z{......};接受大括号内的任何内容作为x2的合法初始值设定项,并且事实上初始化x2

1 个答案:

答案 0 :(得分:5)

这是一个从C ++ 98继承的不稳定的设计问题:某些转换或初始化在语法上限于文字,特别是字符串文字作为char数组的初始值设定项([dcl.init.string] / 1)和整数文字作为空指针常量([conv.ptr] / 1)。当然,这与“完美”转发并不顺畅。

对于空指针,引入nullptr可以避免问题,可以使用0代替X,并且即使在转发后也能正常工作。

在您的情况下,基本上有两个主要选项:

  • 利用大括号 - struct X { X2 x2; } z{1, 2, "abc"}; // Ok 也是一个集合:

    buf
  • 声明std::string具有类类型,例如let或者,或许在您的情况下更合适一些静态大小的等效物(限于10号)。