1. 39
  1.  

  2. 14

    In my opinion, if a C or C++ formatter reorders #includes, that is a bug in the formatter. Remember, #include is just a simple copy-paste macro. Reordering #includes changes the source code in a non-trivial way. Over the years I have seen many headers - even in standard headers that shipped with the compiler - that had a variety of side-effects and even caused errors if the order were any different. Just a simple using namespace std; in your header makes reordering deadly. Or forward declarations. Should you write your headers like that? No. Does it happen in the wild? Yes, all the time.

    1. 7

      We had some wonderful build issues related to this at my last job.

      There was a super old header that #defined a few key constants. This header was usually #included into just about every compilation unit in the company. Sometimes these constants were needed in a protobuf-like layer, so we would end up generating code with enums that had the same name as the #defined constants.

      For example:

      old.h:

      #define RED 1
      #define BLUE 2
      

      proto.hpp:

      enum { RED = 1, BLUE = 2 };
      

      im_trying_to_do_my_best_here.cpp:

      #include <iostream>
      // .. a million headers ..
      #include <enterprise_fun_time.hpp>   // includes <old.h>
      // ... a million more headers ...
      #include <proto.hpp>
      

      Compiling the above gives you an error message that "enum { 1 = 1, 2 = 2 }" is just silly. Fixing this was a trick sometimes; it’s hard to trace where transitive includes are coming from. This kind of issue also more common than I’d like to admit :).

      I personally like that clang-format rearranges headers. Though yes, it can break your build (or even change your program!). I think encouraging C/C++ developers to do their best to have order-independent headers is a Good Thing™. I suppose it could always be turned off with the IncludeBlocks option in clang-format.

    2. 9

      It sometimes amazes me that we’ve ever managed to make anything work at all.

      1. 6

        It is no surprise that (spoiler) include order has side effects. Will C++ modules be different?

        1. 3

          The surprise is meant to be the subtle nature of the side effects and also the fact that clang clang-format does it automatically.

          1. 2

            clang-format, not clang.

          2. 1

            Right, I mean some headers are designed with the use of side effects in mind, like

            #define _GNU_SOURCE
            #include <string.h>
            

            I guess you’re supposed to #undef it afterwards to clean up your state, but most people don’t do that. IIRC Python sets _GNU_SOURCE globally in pyconfig.h.

            The issue isn’t limited to C: changing the import in Python can have even worse arbitrary side effects. Python formatters may do that too IIRC.