I can write this simple struct:
struct Person {
std::string name;
my_complicated_date_type date_of_birth;
};
and get serialization, network interop, logging, automated UI generation, hashing, type-safe IDs, etc. without having to write an additional line of code. Twenty years ago you had to write 2000 lines of additional boilerplate for each data type to get to the same place.Arguably the result would have been easier to read and maintain and not as slow to compile.
having been through I don't know how many codegen frameworks I thoroughly disagree, those are a complete pain to maintain as soon as you want to support mac / windows (esp. MSVC) / linux / wasm and various brands of cross-compiling. Everything that can be done in the target language, should.
Or is your concern about integration into the build system of any prebuild-events or similar logic that need to be run in addition to compiling and linking? This integration may require separate efforts for each platform. But such support is very useful for a bunch of different things in most non-trivial projects, such that it's better to pay for that effort early, rather than develop workarounds to avoid it in my experience.
you can't do that as soon as you start thinking about embedding non-code resources in your binaries, etc. #embed / std::embed is finally solving this though. You also usually have to think a lot about linking, symbol visibility & various other compiler-specific attributes in such files if you're doing non-trivial work.
> Or is your concern about integration into the build system of any prebuild-events or similar logic that need to be run in addition to compiling and linking? This integration may require separate efforts for each platform.
Exactly, and my experience is that it is always not worth it. For example I ported all my Qt code so that it doesn't use moc (external code generator) and uses instead verdigris (same thing with slightly more complex macros but no need for anything else than a c++ compiler for building my code) and that instantly solved so many problems it's not even funny - something that required maintenance multiple times a year (pretty much every time you want to use some new C++ feature and the code generator does not know yet how to parse a source file that contains this feature - I have issues open on the Qt bug tracker that are now well into their first decade) had its operational cost fall to 0. And moc is by far one of the most well-developed code generators I've had to use, so many others just fail on anything other than the "happiest path".
The only vaguely tolerable experience I had was using CMake as a code generator as cmake works portably-enough on the platforms it supports (though there are oddities to take care of between MSYS2 CMake and MinGW CMake and MSVC CMake) but then there's a lot of people who will absolutely never ever want to touch this (https://github.com/ossia/score/blob/master/cmake/GenerateLic...) or this (https://github.com/ossia/score/blob/master/cmake/ScoreFuncti...) with a ten foot pole. If I could replace all this today with normal C++ code I absolutely would in a heartbeat, it would be an undebatable improvement even if it took three times as many LoC / tokens / cyclomatic complexity / whatever measure you want to use.
You do the best you can, today, with what you have, and then you ship it and get on to the next challenge. Same now as it always was.
The problem with C++ is that you end up having to take most of its features into account, one way or the other, and it quickly gets complicated; at least that's my experience and the experience of many others.