I'm looking for a way to initialize non-moveable members in a structure through a factory function return value. Specifically, the language admits the case of initializing a non-moveable member through aggregate initialization, but there are scenarios in which this kind of initialization is not possible. I wonder if there is still a way to initialize non-moveable members directly (in-place) in cases where aggregate initialization is not permitted.
This is a similar question, although it deals with the case of initializing a non-static member from a function returning a non-copyable/moveable type.
An example is in order. Consider the following:
struct S { S(S&&) = delete; }; // Non-moveable type.
S F() { return {}; }
Now, consider the following initialization of a member in an aggregate from a return value.
struct T { S s; };
void G() { T t{F()}; } // OK (in-place construction of t).
The above works because t
is being initialized through aggregate initialization. S::S(S&&)
is not involved. [Note: this excerpt works only in GCC-7, not in GCC-6 or older versions.]
But what if aggregate initialization is not possible at all?
struct X {};
struct U: virtual X // Not an aggregate anymore.
{ S s; U(S&& s): s{(S&&)s} {} }; // Needs an explicit constructor.
void H() { U u{F()}; } // Doesn't work (S::S(S&&) is deleted).
...or simply inconvenient?
struct A {}; struct B {}; struct C {};
struct V: A, B, C { S s; }; // Still an aggregate.
void I() { V v{F()}; } // No chance.
void J() { V v{{}, {}, {}, F()}; } // Kinda works, but ugly.
The point here is that, although S
in non-moveable, it would be nice if it could be used as a member object subject to in-place construction in situations similar to the above.
Is it possible?