One corner case is that b() might use variables that are initialized further down in the file. Some languages, such as Javascript, lift function definitions to the top so you can call functions defined below you, but it's harder to do the same for variables. In a compiled language it should be possible to detect this at compile time, but it's fiddly and more complicated than having a main function.
>> JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables, classes, or imports to the top of their scope, prior to execution of the code.
>> Hoisting is not a term normatively defined in the ECMAScript specification. The spec does define a group of declarations as HoistableDeclaration, but this only includes function, function*, async function, and async function* declarations. Hoisting is often considered a feature of var declarations as well, although in a different way. In colloquial terms, any of the following behaviors may be regarded as hoisting:
>> Being able to use a variable's value in its scope before the line it is declared. ("Value hoisting")
>> Being able to reference a variable in its scope before the line it is declared, without throwing a ReferenceError, but the value is always undefined. ("Declaration hoisting")
>> The declaration of the variable causes behavior changes in its scope before the line in which it is declared.
>> The side effects of a declaration are produced before evaluating the rest of the code that contains it.
So basically all the shit we take for granted when not writing C/C++. What is curious to me is whether the main reasons for not attempting this in a C++ compiler in 2023, or else moving the language spec in this (unofficial) direction, is to produce maximal performance-optimization, or if it's mostly a cultural thing at this point. It does have the benefit of turning away hordes of javascript kiddies from the gates, but, the relative value of the performance edge to any optimization is getting weaker as compute becomes cheaper.
The genie got somewhat out of the bottle with constructors: C++ will call constructors to initialize static variables. In theory we could use this mechanism to allow top-level statements. However, these static initializers are so full of footguns that perhaps it's best we don't :P