Stack Factory Puzzle -- Alex Marmer

When instances of classes derived from the same class need to be created based on certain conditions, they are created on the heap. The puzzle is about how to do it on the stack.

Stack Factory Puzzle

By Alex Marmer

 

Add a Comment

You must sign in or register to add a comment.

Comments (4)

0 0

Bertin Colpron said on Sep 12, 2018 05:14 AM:

I would use a variant but I would have to #include it first (which isn't possible the Begin-End block). Here's my answer nevertheless:


std::variant<int,X0,X1,X2> x;
if (i == 0) {
x.emplace<X0>();
pX = &std::get<X0>(x);
} else if (i == 1) {
x.emplace<X1>();
pX = &std::get<X1>(x);
} else {
x.emplace<X2>();
pX = &std::get<X2>(x);
}


Run the code here: https://coliru.stacked-crooked.com/a/99ae3df37995553f

Yields the expected output. The leading "int" variant template argument is necessary for default variant initialization.
0 0

Emanrov E. Emanhcan said on Sep 12, 2018 02:58 PM:

My solution involves a char array on the stack in conjunction with 'placement new' and a unique_ptr with a lambda deleter function.

https://coliru.stacked-crooked.com/a/602622223a42c3bb


// Begin
constexpr auto size = std::max(
alignof(X0) - 1 + sizeof(X0),
std::max(
alignof(X1) - 1 + sizeof(X1),
alignof(X2) - 1 + sizeof(X2)
)
);

char memory[size];

if (i == 0) {
void* ptr = memory;
auto space = size;
pX = new (std::align(alignof(X0), sizeof(X0), ptr, space)) X0;
}
else if (i == 1) {
void* ptr = memory;
auto space = size;
pX = new (std::align(alignof(X1), sizeof(X1), ptr, space)) X1;
}
else {
void* ptr = memory;
auto space = size;
pX = new (std::align(alignof(X2), sizeof(X2), ptr, space)) X2;
}

std::unique_ptr<X, void (*)(X*)> x{
pX,
[](X* ptr) { ptr->~X(); }
};
// End

0 0

Dennis Börm said on Sep 12, 2018 09:55 PM:

for default variant initialization:

https://en.cppreference.com/w/cpp/utility/variant/monostate
0 0

Dennis Börm said on Sep 13, 2018 12:02 AM:

https://github.com/amarmer/Stack-Factory-Puzzle/issues/3#issuecomment-420779367

but std::variant::emplace uses placement new too (at least in STL of gcc8.2.1)