Search code examples
c++c++11constantsostream

why is std::basic_ostream::operator<< not const-qualified?


First, an example to illustrate the morals behind my question: the below code will not compile, because std::basic_ostream::operator<< is not const-qualified. (https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-3.4/ostream-source.html shows that the operator is not const-qualified.)

I compiled with GNU g++ 6.4.0 compiler, with --std=c++11 flag on.

#ifndef TEST_H
#define TEST_H
#include<string>
#include<iostream>
using namespace std;
class ChessPiece{
    const string name;
    const int side;
public:
    ChessPiece(const string&,const int);
    void printPiece(const ostream&) const;
};
#endif // TEST_H

...and test.cpp.

#include"test.h"
ChessPiece::ChessPiece(const string& s,const int bw): name{s}, side{bw} {}
void ChessPiece::printPiece(const ostream& S=cout) const{
    S << "a " << (side==1?"white ":"black ") << name << endl;
}
int main(){
    ChessPiece p{string("pawn"),-1}; // a black pawn
    p.printPiece();
}

However, I am not sure as to why these kind of errors should occur in the first place, even though operator<< is, as in the above code, logically const. Yes, the obvious answer would be that "operator<< changes the inner state of std::ostream in some way".

However, I know that by making the members mutable we can change the contents of the class, as long as the const-qualified function is logically const. I also know that an instance of std::ostream will not logically differ in any way before and after calling its operator<<. (If anything I wrote is wrong, please point it out. Thank you)

Rephrased,

Why is the logically const std::basic_ostream::operator<< not const-qualified, instead of having some of its members mutable?

Thank you in advance.


Solution

  • You said:

    I also know that an instance of std::ostream will not logically differ in any way before and after calling its operator<<.

    That's one way to look at an std::ostream. Another way to look at it is that it is an interface to a device -- a file, a console, a string, etc. If a member function in that interface changes the underlying device, it is misleading to make that member function a const member function.

    The notion of const is conceptual. Take a look at one my answers that explores the subject a bit. Yes, one could have made the operator<< functions work with const std::stream objects but it makes more sense that they are not. They are changing the underlying device that they provide an interface for and, IMO, it's better that they work with non-const objects of type std::ostream.