I've found that the way I'm most productive is by using data-oriented design where I put everything in structs and don't use classes. I still use a lot of modern C++ library features, but it reads more like C.
For example:
struct BufferPool
{
alignas(PAGE_SIZE) char frames[BUF_POOL_NUM_FRAMES][PAGE_SIZE];
std::atomic_uint32_t free_frames[BUF_POOL_NUM_FRAMES];
std::atomic_uint32_t pin_count[BUF_POOL_NUM_FRAMES];
std::atomic_bool is_dirty[BUF_POOL_NUM_FRAMES];
std::atomic_uint32_t page_id_to_frame_idx[];
};
std::span<const char>
BufferPool_get_record(BufferPool* pool, RecordID rid, int db_file_fd);
What's nice about having all this stuff thrown into the language is that you're free to pick and choose what you want to adopt from it.For a long time, I tried to cram everything I wrote in C++ into an OOP pattern with classes, and it just didn't jive with me. Then I stopped doing that and started writing it more like TypeScript/Kotlin/C which I'm more familiar with and it's been a lot more pleasant ever since.
There's been so much great stuff in C++ 17/20/23 and you can just cherry pick all the bits you want to use out of it and ignore the rest.