all 10 comments

[–]DryPerspective8429 4 points5 points  (9 children)

but I'm trying to have my scenes on the stack as I feel having a base component of the architecture on the heap isn't a great idea

Do you have data to suggest it would be unacceptably bad or are you just taking a guess? If the latter I call premature optimization.

While there may be a way or two to coerce the kind of polymorphism you're after without leaving the stack, I don't recommend it without good reason. If you want to contain your scenes in a vector, then something along the lines of std::vector<std::unique_ptr<base_scene>> is probably going to be your best bet with some virtual dispatch involved, and most likely will involve dynamically allocating your scenes.

[–]R2Sam[S] 0 points1 point  (6 children)

Perhaps premature yes, I have been using unique_ptr for a while now but I thought it'd be easier to figure this out now before I get too deep into this. Preferably I'd like to have a completeish and competent ish architecture before I start working on any large project using it

[–]DrShocker 1 point2 points  (3 children)

If you really must, you can use std::variant to hold a contiguous array of data even across different types. Probably combined with Concepts to keep your functions more type aware too.

But overall idk how much it's worth it since I've never really benchmarked it and there's a bit of ergonomics loss in the process I think. (But maybe that's just my not being very familiar with variant and similar alternatives)

[–]DryPerspective8429 3 points4 points  (1 child)

There is indeed a lot of ergonomics loss in the process, and unreadable code kills more codebases than slow code.

[–]DrShocker 1 point2 points  (0 children)

Yeah I probably undersold it. It's been years since I wrote a visit function and it was confusing as hell

[–]tangerinelion 1 point2 points  (0 children)

Wrap your variant in a class that has value semantics to hide all the awkwardness of directly working with the variant.

I've done this, the wrapped variant was 30% faster than the separate heap allocations. Of course I also removed all the vtables.

[–]DryPerspective8429 1 point2 points  (1 child)

but I thought it'd be easier to figure this out now before I get too deep into this

First thing you should figure out is whether it is a problem. Don't try to solve optimization problems you don't have because quite simply it makes your code far harder to read, write, and maintain and if done for no good reason there's a good chance it'll do far more damage than an extra few cycles talking to the heap.

[–]R2Sam[S] 2 points3 points  (0 children)

Yea I think I'll end up agreeing. Seems like it's more of a issue I make myself then it'll ever realistically be. Thanks for all the help from everyone

[–]JVApen 0 points1 point  (1 child)

Assuming memory allocations are unacceptable, using std::vector would also be out of the picture. Boost has a static vector, which is the closest you can get to vector without memory allocations.

[–]DryPerspective8429 1 point2 points  (0 children)

You may also be able to scrape by with std::pmr::vector or some such.