Perfect forwarding fails when the target is aggregated with an 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 } 

The last line gives an error: 17 : error: invalid conversion from 'const char*' to 'char' [-fpermissive]

If I use std::forward(args)... instead of args... , there are even more errors; and there are also errors if I try to use {'a', 'b', 'c', '\0'} as an initializer instead of a string literal.

Is there any way to make this work, i.e. allow X z{......}; when is anything inside braces that would be a legal initializer for x2 accepted and actually initializes x2 ?

+7
c ++ perfect-forwarding aggregate c ++ 14
source share
1 answer

This is not a simple design problem that was inherited from C ++ 98: some transformations or initializations are syntactically limited to literals, in particular string literals as initializers for char arrays ([dcl.init.string] / 1) and integer literals as null pointer constants ([conv.ptr] / 1). This, of course, is not well suited for an "ideal" forwarding.

For null pointers, the problem was circumvented by introducing nullptr , which can be used instead of 0 and works fine even after redirecting.

In your case, there are two main options:

  • Exploit Sketch - X also an aggregate:

     struct X { X2 x2; } z{1, 2, "abc"}; // Ok 
  • Declare buf to have a class type, for example. std::string or perhaps the equivalent static size (limited to 10) in your case.

+5
source share

All Articles