C and C++ are languages that have chosen to be one step, that is, they analyze what they find in the order and evaluate what to do with that in the order that came.
Modern languages tend to avoid this limitation, although compilation performance suffers somewhat.
In the past that gain was very important today is not more. But it is possible that some codes use this feature and a change could break the compatibility of C and C++.
The most modern languages work with two-step compilation (not to be confused with phases). Then there is a reading and "interpretation" of some points of the code and only then other points are evaluated. In general what is of the highest level such as the declaration of global types, structures and information, as are the functions, is that they are evaluated in the first step, then the compiler has a table of symbols and additional information of how they are composed to use in the second step. This way the order as each thing was declared doesn’t matter. This gives more flexibility by charging the price of performance.
I told you about PHP.
Note that the compiler only needs to know the job signature to see if your code is calling in accordance with what has been declared, just need to check the contract, do not need the function set before because this is implementation details, including the code of the function might not even be in that file or even compilation unit, could come from a static or dynamic library, as it is in other languages.
More modern languages often have metadata files with signatures when the source is not available (or they read the entire source, typical case of interpreted languages, which is much worse).
In C and C++ you need the sources at least of the function signatures and the structures and other global information that can be made available externally. Again modernity brought something that these languages could not have at the time. This is solved with so-called headers.
C++ could have changed that but lost some compatibility with C. But now they don’t care that much and found a way to have some modernity without breaking compatibility.
One can work with modules in C++20 forward. They are implemented in the same modern way that Rust and other languages use and the statements do not need to be present before use, as long as they exist and are present in a module, which is something new in the language, and of course, that it has been imported. Modules are much more than this. Documentation. Proposal. Presentation.
When I was researching I found Why, in C, a function needs to be declared before it is used?, maybe a duplicate, except for the last paragraph I answered here.