As others have noted, this is undefined behavior (so unsafe) even though it is likely to work for POD types with no virtual members or bases. It's easy enough to do it safely by just defining the appropriate constructor:
#include <array>
struct Foo : std::array<int,3>
{
Foo() : std::array<int,3>({1,2,3}) {}
void hello() { std::cout << "Hello\n"; }
Foo(const std::array<int, 3> &a) : std::array<int,3>(a) {}
};
Foo test()
{
std::array<int,3> a{4,5,6};
return a;
}
and then no cast is actually needed.
If for some bizarre social reason (assignment requirements?) you're not allowed to change the definition of Foo, you can get around this by using an adaptor class:
struct Foo : std::array<int,3>
{
Foo() : std::array<int,3>({1,2,3}) {}
void hello() { std::cout << "Hello\n"; }
};
struct FooAdaptor : public Foo {
FooAdaptor(const std::array<int, 3> &a) {
*this = a;
}
};
Foo test()
{
std::array<int,3> a{4,5,6};
return FooAdaptor(a);
}
but I would not recommend this for real code