Is there any situation where you wouldn't want include guards?

前端 未结 6 733
北海茫月
北海茫月 2021-01-11 22:08

I know why include guards exist, and that #pragma once is not standard and thus not supported by all compilers etc.

My question is of a different kind:<

相关标签:
6条回答
  • 2021-01-11 22:18
    <cassert>
    <assert.h>
    

    "The assert macro is redefined according to the current state of NDEBUG each time that <assert.h> is included."

    0 讨论(0)
  • 2021-01-11 22:20

    It can be a problem if you have two headers in a project which use the same include guard, e.g. if you have two third party libraries, and they both have a header which uses an include guard symbol such as __CONSTANTS_H__, then you won't be able to successfully #include both headers in a given compilation unit. A better solution is #pragma once, but some older compilers do not support this.

    0 讨论(0)
  • 2021-01-11 22:22

    Suppose you have a third party library, and you can't modify its code. Now suppose including files from this library generates compiler warnings. You would normally want to compile your own code at high warning levels, but doing so would generate a large set of warnings from using the library. You could write warning disabler/enabler headers that you could then wrap around the third party library, and they should be able to be included multiple times.

    Another more sophisticated kind of use is Boost's Preprocessor iteration construct: http://www.boost.org/doc/libs/1_46_0/libs/preprocessor/doc/index.html

    0 讨论(0)
  • 2021-01-11 22:25

    @sbi already talked about code generation, so let me give an example.

    Say that you have an enumeration of a lot of items, and that you would like to generate a bunch of functions for each of its elements...

    One solution is to use this multiple inclusion trick.

    // myenumeration.td
    MY_ENUMERATION_META_FUNCTION(Item1)
    MY_ENUMERATION_META_FUNCTION(Item2)
    MY_ENUMERATION_META_FUNCTION(Item3)
    MY_ENUMERATION_META_FUNCTION(Item4)
    MY_ENUMERATION_META_FUNCTION(Item5)
    

    Then people just use it like so:

    #define MY_ENUMERATION_META_FUNCTION(Item_) \
      case Item_: return #Item_;
    
    char const* print(MyEnum i)
    {
      switch(i) {
        #include "myenumeration.td"
      }
    
      __unreachable__("print");
      return 0; // to shut up gcc
    }
    
    #undef MY_ENUMERATION_META_FUNCTION
    

    Whether this is nice or hackish is up to you, but clearly it is useful not to have to crawl through all the utilities functions each time a new value is added to the enum.

    0 讨论(0)
  • 2021-01-11 22:31

    I've seen headers that generate code depending on macros defined before their inclusion. In this case it's sometimes wanted to define those macros to one (set of) value(s), include the header, redefine the macros, and include again.
    Everybody who sees such agrees that it's ugly and best avoided, but sometimes (like if the code in said headers is generated by some other means) it's the lesser evil to do that.

    Other than that, I can't think of a reason.

    0 讨论(0)
  • 2021-01-11 22:32

    The problem with #pragma once, and the reason it is not part of the standard, is that it just doesn't always work everywhere. How does the compiler know if two files are the same file or not, if included from different paths?

    Think about it, what happens if the compiler makes a mistake and fails to include a file that it should have included? What happens if it includes a file twice, that it shouldn't have? How would you fix that?

    With include guards, the worst that can happen is that it takes a bit longer to compile.

    Edit: Check out this thread on comp.std.c++ "#pragma once in ISO standard yet?"

    http://groups.google.com/group/comp.std.c++/browse_thread/thread/c527240043c8df92

    0 讨论(0)
提交回复
热议问题