Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::ostream recognize without defining header

I created this code:

Main.cpp

#include <iostream>
#include "Quote.h"

int main()
{
    derived().print(std::cout);

    getchar();
    return 0;
}

Quote.h

#pragma once
#include <string>

class base {
public:
    std::string name() { return basename; }
    virtual void print(std::ostream &os) { os << basename; }

private:
    std::string basename = "abc";
};

class derived : public base {
public:
    void print(std::ostream &os) { base::print(os); os << " " << i; }

private:
    int i = 0;
};

If I don't include the iostream header file in Main.cpp, as expected, std::cout is not recognized. My question is: Why there's no problem with the use of std::ostream in Quote.h if iostream is not included?. Either cout as ostream are defined in the aforementioned library, why the cout use is a problem and ostream not?

I'm using VS 2017, in case this info is important.

like image 524
Edgar Hernandez Avatar asked Oct 19 '25 02:10

Edgar Hernandez


1 Answers

All existing answers concentrate on #include <string>. I'd like to point at another side. Consider slightly modified version:

quote.h:

#pragma once

// uncomment to get an analog of original example
// #include <string>

struct Quote {};

std::ostream& operator<<(std::ostream& os, Quote const&)
{
    return os << "quote\n";
}

main.cpp:

#include <iostream>
#include "quote.h"

int main()
{
    std::cout << Quote{};
}

As you see #include <string> is commented out, quote.h still doesn't include iostream and the program still compiles. It does because only source files (.cpp, or translation units) are directly compiled. Headers are literally included. Now if we literally include quote.h in main.cpp we get:

#include <iostream>

// uncomment to get an analog of original example
// #include <string>

struct Quote {};

std::ostream& operator<<(std::ostream& os, Quote const&)
{
    return os << "quote\n";
}

int main()
{
    std::cout << Quote{};
}

(online)

It's what actually gets compiled. Notice everything is alright here, #include <iostream> before std::ostream usage.

And as was correctly pointed in comment to another answer, this is an example why it's important to always maintain self-sufficient headers that include all headers they depend on.

As @Evgeny pointed out in the comment, please check recommendations about organising our includes.

like image 195
Andriy Tylychko Avatar answered Oct 21 '25 15:10

Andriy Tylychko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!