1

While looking for best pratices regarding include order, I was stumbling over this thread:

C/C++ include file order/best practices [closed]

@squelart was stating, that it is better pratice to include from local to global, as this reduces the chance of hidden dependencies. I just tested this in a VS2015 project with the following code:

StrTest.h

#pragma once

class CStrTest
{
    public:
        CStrTest();
        ~CStrTest();

        std::string test;
};

StrTest.cpp

#include <string>
#include "StrTest.h"


CStrTest::CStrTest()
{
}

CStrTest::~CStrTest()
{
}

I couldn't reproduce the stated behaviour (hidden dependencie duo including string first in StrTest.cpp). The compiler gives me mulitple errors. So is this something out of the past or did I overlook something?

EDIT: VS2015 Compiler errors:

Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int

Error C2039 'string': is not a member of 'std'

Error C3646 'test': unknown override specifier

YokeM
  • 75
  • 6
  • It's unclear what you're asking here - the above code compiles. – Oliver Charlesworth May 30 '17 at 08:59
  • 1
    You are actually doing the opposite of what squelart answer suggested. – user7860670 May 30 '17 at 09:03
  • 1
    You also need to include or at least forward declare `std::string` in `StrTest.h`. You header files should be self contained. – juanchopanza May 30 '17 at 09:06
  • 1
    @VTT which is YokeM's point as I understand it. They are attempting to do the opposite and reproduce the problem with implicit dependency - i.e. program that compiles even though all dependencies of the header are not satisfied. According to YokeM, the problem is not reproduced in VS2015 which "gives multiple errors". – eerorika May 30 '17 at 09:12
  • @user2079303: Thank you, that was my point. I also added the VS2015 compiler errors. – YokeM May 30 '17 at 09:23
  • I'll bet it's that non-standard `#pragma once` that's messing things up. What happens when you use normal include guards? – Pete Becker May 30 '17 at 18:20

2 Answers2

1

So is this something out of the past

No, the hidden dependencies are the standard behaviour and do happen in modern compilers. I don't know of VS, but GCC and Clang do compile your shown program without any errors. Demo: https://wandbox.org/permlink/ATJndwrOwirpDgDd

The compiler gives me mulitple errors.

Although an "implicit" include is poor style, it is still technically well formed as far as the standard is concerned as long as the implicitly included file is guaranteed to be included by you or whoever wrote the header that includes it - standard headers have no such guarantees.

Therefore I would be against such compiler feature that considers implicit includes as errors. An explicitly enable-able warning would be much more suitable.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thank you, I didn't test this with other compilers. It's interesting to see, that this works with GCC and Clang. – YokeM May 30 '17 at 09:26
0

I think the point of hidden dependence problem discussed there is that typically each file includes several other files and if header is not self-contained then including it may work in cases when it's implicit dependences are included by some other header and break everything when those other headers change and / or get moved / removed. In short: use of headers with hidden dependencies lead to extremely fragile code.

// foo.hpp
#pragma once

#include <string> // if we remove this unrelated `StrTest.h` header will be broken
...

.

// main.cpp

#include "foo.hpp" // if we move this one line lower `StrTest.h` header will be broken
#include "StrTest.h" // accidentally works fine
...
user7860670
  • 35,849
  • 4
  • 58
  • 84