I would basically write the following piece of code. I understand why it can't compile.
A instance; // A is a non-default-constructable type and therefore can't be allocated like this
if (something)
{
instance = A("foo"); // use a constructor X
}
else
{
instance = A(42); // use *another* constructor Y
}
instance.do_something();
Is there a way to achieve this behaviour without involving heap-allocation?
There are better, cleaner ways to solve the problem than explicitly reserving space on the stack, such as using a conditional expression.
However if the type is not move constructible, or you have more complicated conditions that mean you really do need to reserve space on the stack to construct something later in two different places, you can use the solution below.
The standard library provides the aligned_storage
trait, such that aligned_storage<T>::type
is a POD type of the right size and alignment for storing a T
, so you can use that to reserve the space, then use placement-new to construct an object into that buffer:
std::aligned_storage<A>::type buf;
A* ptr;
if (cond)
{
// ...
ptr = ::new (&buf) A("foo");
}
else
{
// ...
ptr = ::new (&buf) A(42);
}
A& instance = *ptr;
Just remember to destroy it manually too, which you could do with a unique_ptr
and custom deleter:
struct destroy_A {
void operator()(A* a) const { a->~A(); }
};
std::unique_ptr<A, destroy_A> cleanup(ptr);
Or using a lambda, although this wastes an extra pointer on the stack ;-)
std::unique_ptr<A, void(*)(A*)> cleanup(ptr, [](A* a){ a->~A();});
Or even just a dedicated local type instead of using unique_ptr
struct Cleanup {
A* a;
~Cleanup() { a->~A(); }
} cleanup = { ptr };
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