Search code examples
c++language-lawyerrefactoring

Can the order of declarations alter a program?


That is can you by altering the order of declaration still have a valid program, but with a different result. This question is not if you can turn a valid program into an invalid (which you obviously can).

I expect that this could happen on different level of certainty, from the standard mandates different behaviour to fx "just" introducing undefined behaviour.

The question is a bit how confident one should be in rearranging the (overall) source layout. Could one be reasonably sure that things still works the same if it still compiles?

I guess this is a bit of asking about situations where order will/may matter, since it's now obvious that such situations exist (and if there's trivial countermeasures).


Solution

  • Yes, there are many ways in which the order can matter:

    • Name lookup can result in different entities depending on whether the declaration containing the point of the lookup is before or after another declaration. Example: https://godbolt.org/z/cY7jM9s3d
    • Overload resolution and partial specialization matching considers only previously-declared entities and it is (usually) perfectly valid to declare better candidates later. Example: https://godbolt.org/z/fY367a85q
    • Whether or not a function is previously-defined (rather than just declared) can affect whether or not expressions are constant expressions, which in turn can affect other things like overload resolution. Similarly, whether or not a const integral or enumeration variable has a previous initialization sometimes affects whether or not it can be used in a constant expression.
    • The order of initialization of static storage duration objects depends (sometimes) on the order in which their definitions appear. Changing the order can change the results of the initializations if they depend on one-another.
    • etc.

    There is even one infamous mechanism that can be used to introduce actual compile-time state, via so-called friend-injection.

    And even worse, changing the order of declarations can even affect parsing. During parsing of C++ there are many situations in which it is necessary to check whether a name refers to a type or template and the result will affect how following tokens are interpreted. It is possible that the following code parses differently depending on whether or not a type or template declaration for a given name is present before that point.