If not then that'd be the 3rd type of initialization it's missing, the equivalent of C++'s nothing specified.
People want to initialize stuff at load library time. They will always want to do this. If the language doesn't provide a solution, people will just bolt on shitty add-on toolchains to do it anyway.
This isn't a uniquely C++ problem (__attribute__((constructor)) is after all for C, not C++).
Take for example Rust, which also doesn't provide an attribute((constructor)) equivalent and says nothing happens before or after main. Except https://crates.io/crates/ctor exists to immediately say "fuck that noise" and racked up >20m downloads.
You realize Java has the feature you're discussing, without dependency injection?
class Foo {
static {
initialize();
}
}
They even have a well defined execution order:https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.htm..., section 8.7, with order defined in section 12.4
You can order the init sections on your own when you generate the binaries and add your own constraints, and if your toolchain doesn't give you that control, you can generate and call your own init functions. (Since I didn't want to dick with the linker too much, I generated my own init functions in my natively compiled language to solve this problem).
Your language's dlopen wrapper can also dlsym the initializer and call it if it's present.
This is very much a C++ problem, because its separate compilation model throws away initializer ordering, and prevents the compiler from doing anything about it. And, of course, compatibility makes this a tough sell for C++ -- languages unconstrained by history don't have to worry about this.
tl;dr: Ignore the constructor attribute/init section, and generate your own function that orders things correctly. Then call it before main.