#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 error: 17 : error: invalid conversion from 'const char*' to 'char' [-fpermissive]
If I use std::forward(args)...
instead of args...
then even more errors come up; and also there are errors if I try to use {'a', 'b', 'c', '\0'}
as initializer instead of the string literal.
Is there a way to make this work, i.e. allow X z{......};
where anything inside the braces that would be a legal initializer for x2
, is accepted and does in fact initialize x2
?
This is a precarious design issue that was inherited from C++98: Certain conversions or initializations are syntactically restricted 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). That, of course, doesn't go well with "perfect" forwarding.
For null pointers, the issue was circumvented by introducing nullptr
, which can be used instead of 0
and works fine even after being forwarded.
In your case, there are basically two major options:
Exploit brace elision - X
is an aggregate, too:
struct X {
X2 x2;
} z{1, 2, "abc"}; // Ok
Declare buf
to have class type, e.g. std::string
or, perhaps more appropriate in your case, some statically sized equivalent (limited to size 10).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With