c++gccheader-files

How can I determine what header calls another header in c++?


I am reading from here : Can std::string be used without #include <string>?, <iostream> is calling <string>. But I do not see any includes of <string> in Standard library header <iostream> from c++ standard: https://en.cppreference.com/w/cpp/header/iostream. In <iostream> is only included <ios>, <streambuf>, <istream> and <ostream> according to that documentation. So this code works (file foo.cpp):

#include <iostream>

int main(){
    std::cout << "enter srting\n";
    std::string out; //std::string should not be included according to standard documentation
    std::cin >> out;
    std::cout << "test, " << out;
}

But I have to try to see dependecies generated from gcc:

cc -H foo.cpp |& vim -

and the output is (I have regex out files with string in it):

. /usr/include/c++/8/iostream
..... /usr/include/c++/8/bits/stringfwd.h
...... /usr/include/c++/8/string
....... /usr/include/c++/8/bits/basic_string.h
........ /usr/include/c++/8/ext/string_conversions.h
....... /usr/include/c++/8/bits/basic_string.tcc

So I can see that in the end, many "string" headers are indeed included

  1. (so should I trust that documentation, when the did not mentioned <string> header in "Includes" list of <iostream>?).

Some of them are deeper on the #include stack (term from gcc manual), which brings me to question,

  1. what calls what? And what is the "true" header, that define std::string of them? (is it /usr/include/c++/8/bits/basic_string.h?...)

from this question Why does omission of "#include <string>" only sometimes cause compilation failures?, they mentioned:

Some compilers on some platforms may on some time of the month compile even though you failed to include the header

But from the upper output of the "string headers", there is multiple of them , so how's possible for a compiler to compile only sometimes? Which of these headers are really important for successful compilation?

  1. How to orient in cpp headers, which are meaningful for compiler, and could be tracked their "#include stack" (i.e. other meaningful headers)?

EDIT: If it depends on my specific implementation of my stdlib++, then I want to know how can I determine from source whether that inclusion is made before I try to compile. Not by "If it compiles, then it works".


Solution

  • You should always check the documentation for any symbol you use and include any headers it is specified to require.

    The C++ standard only specifies which symbols must be made available when a standard header is included. It does not place any limits on what other symbols are made available. In your example, the standard specifies the <iostream> must include <ios>, <streambuf>, <istream>, and <ostream>, but <iostream> may include any other headers its authors want. It may also forward-declare any symbols it may need.

    1. (so should I trust that documentation, when the did not mentioned <string> header in "Includes" list of <iostream>?).

    You should trust that the symbols specified as being available when you include <string> will be. That is all. You may not assume that those symbols will not be visible when including any other header.

    1. what calls what? And what is the "true" header, that define std::string of them? (is it /usr/include/c++/8/bits/basic_string.h?...)

    This is an implementation detail that can only be answered by inspecting the implementation's headers. Libstdc++ (the standard library implementation used by GCC) has the declaration of the std::string class in bit/stringfwd.h and its definition in bits/basic_string.h and bits/basic_string.tcc (for the current version, at least), but that is not required at all. If the libstdc++ maintainers decided they wanted to refactor and reorganize things, they would be free to do so. The only requirement that is guaranteed by the C++ language is that std::string must be available when <string> is included.

    But from the upper output of the "string headers", there is multiple of them, so how's possible for a compiler to compile only sometimes?

    Different standard library implementations or different versions of the same implementation could transitively include different headers. Different compiler flags (i.e. a debug flag or different standard compliance mode) could transitively include different headers.

    Which of these headers are really important for successful compilation?

    1. How to orient in cpp headers, which are meaningful for compiler, and could be tracked their "#include stack" (i.e. other meaningful headers)?

    All of them are meaningful. The standard library's authors wouldn't include a header if they didn't need it for something. Just because you aren't using any symbols declared/defined in that header directly doesn't mean none are being used.


    EDIT: If it depends on my specific implementation of my stdlib++, then I want to know how can I determine from source whether that inclusion is made before I try to compile. Not by "If it compiles, then it works".

    The only way to know is to look at your standard library implementation's headers. There is nothing magical about them; they're just C++ code. If you want to know if <iostream> includes a declaration or definition of std::string, open your implementation's copy of <iostream> and look for a declaration or definition of std::string. Repeat this process for any headers that <iostream> includes.