0

so I've been experiencing some strange issues with using #include in header files. The goal is to make so any custom or common systems are all in one place that I can just include in whatever file I'm working on. This has been working so far, but I noticed recently that seemingly for no reason a new header file I add to it won't have access to any code that was included before it like the rest have. It's set up a bit like this:

// includes.h
#include <cstdlib>
#include <iostream>
#include <vector>
#include <map>
#include <random>
#include <cmath>
#include <memory>
#include "a.h"
#include "b.h"
#include "c.h"

Now what's happening is a.h and b.h can use all code from the includes from above them, and b.h can use code from a.h, but seemingly for no reason, c.h cannot use any code from anything included above it, but occasionally making an entirely new header file with a different name will work. I'm unaware as to what could be causing this issue, and would love help understanding this problem. If any more clarification should be provided please let me know.

Shirb
  • 103
  • 5
  • 10
    I recommend you let each of your header files include what they need themselves. – Some programmer dude Oct 12 '22 at 12:02
  • please show a [mre], at a guess your header is included first from somewhere else – Alan Birtles Oct 12 '22 at 12:05
  • Do you have mutual or cyclic dependencies amongst `a.h`, `b.h` and `c.h`? – G.M. Oct 12 '22 at 12:09
  • 1
    I don't know how to provide a reproductible example since it seemingly appears to be happening at random. I tried to make a header file named "World.h" which was unable to access anything included before it in the includes.h file, but when I made one named "test.h" specifically to test this issue I've encountered, I was able to access the code included before it, despite both files being effectively empty apart from one line attempting to use code from before it and both being included in the includes.h file the same way – Shirb Oct 12 '22 at 12:09

2 Answers2

1

Each header should include what they use. It should not be depended on the user to include.

For example: C uses B, and B uses A

  • c.h: #include B.h
  • b.h: #include A.h

Also don't forget to add #pragma once to the headers. this will result that that header file will only be loaded once. For example: if you would have a class D, which includes A.h. It will be only loaded once even though B and D both use A.h.

See also: https://www.incredibuild.com/blog/include-what-you-use-how-to-best-utilize-this-tool-and-avoid-common-issues

https://www.fluentcpp.com/2021/01/01/include-what-you-use/

https://include-what-you-use.org/

RvdK
  • 19,580
  • 4
  • 64
  • 107
  • I was under the assumption that it'd be redundant to have 50 something files all separately include iostream because from how it's been explained to me the compiler more or less copies+pastes the header file code to wherever it was said to be included – Shirb Oct 12 '22 at 12:13
  • @Shirb because of the #ifndef/#define/#endif thing, the file is skipped. Modern compilers are smart enough to realize this, and not even bother processing the file. – user253751 Oct 12 '22 at 12:30
  • [`#pragma once` has *unfixable* bugs. It should never be used](https://stackoverflow.com/a/34884735/440558) (from an old "core GCC developer"). So mayby not always a good idea. – Some programmer dude Oct 13 '22 at 01:09
0

I am not exactly sure. One simple thing you might miss is ensuring each header is included only once. Most likely, you are missing that on the "a.h" or "b.h" file. You should do that in every header file to avoid cyclic dependencies, including "c.h.". You can do that by

#pragma once

or

#ifndef _INCL_GUARD
#define _INCL_GUARD
#endif

See: Why are #ifndef and #define used in C++ header files? https://learn.microsoft.com/en-us/cpp/preprocessor/once?view=msvc-170

  • I'm using CLion which automatically generates the #ifndef #define #endif statements upon creating a new header file – Shirb Oct 12 '22 at 12:30
  • 1
    _INCL_GUARD is a reserved name in C++ - don't use names beginning wit an underscore and uppercase letter in your own code. – Neil Butterworth Oct 12 '22 at 13:12
  • [`#pragma once` has *unfixable* bugs. It should never be used](https://stackoverflow.com/a/34884735/440558) (from an old "core GCC developer"). So mayby not always a good idea. – Some programmer dude Oct 13 '22 at 01:10