0

Why can't I declare a friend function as const?

//Types.h
#pragma once
#include <string>
#include <ostream>

class Player
{
public:
    //constructors
    Player();
    Player(const std::string&, unsigned short);

    //operator overload
    friend std::ostream& operator<<(std::ostream&, const Player&);
//                  (I can't declare it as const)

    //getter
    const std::string& get_id() const;

private:
    std::string id;
    unsigned short lvl;
};
//Types.cpp
#include "Types.h"
#include <iostream>
#include <iomanip>

/*other definitions*/

std::ostream& operator<<(std::ostream& out, const Player& print)
{
    out << "Player: " << std::setw(6) << print.id << " | " << "Level: " << print.lvl;
    return out;
}

I mean, if I want to call operator<< on a constant variable or in a constant function, I will get an error because operator<< is not constant, even if it doesn't change anithing inside the class.

Simo Pelle
  • 141
  • 1
  • 11
  • Your `Player& print` is not constant. – adziri Jan 26 '20 at 21:36
  • I know: my example shows that the friend method could modify any variable if it is not declared as *constant*, so I can't understand why my compiler does not allow me to declare it as a `const` function – Simo Pelle Jan 26 '20 at 21:48
  • No, your example shows that you can modify `print` since it is not declared `const`. Since the friend function is not a member function, there is no `this` variable in it that could be `const` and therefore, you cannot add the `const` modifier to the function itself. – flyx Jan 26 '20 at 22:07
  • @flyx what I mean is that I declare a function as `const` if I want it to be called in another `const` function or on a parameter passed by `const` reference, but if this function is a `friend` I can't do it because it can't be declared as `const`. So (don't think to my example) if I want to call `operator<<` (which doesn't modify any variable) on a `const` variable, I can't do that because `operator<<` can't be declared as `const` – Simo Pelle Jan 26 '20 at 22:37
  • I couldn't fully understand your comments. but I think what you need is `std::ostream& operator<<(std::ostream& out, const Player& print)` – asmmo Jan 26 '20 at 23:01
  • @anonymous I edited the post to make it a bit more clear... I don't know how to explain you if you can't understand this! – Simo Pelle Jan 26 '20 at 23:11
  • You _can_ call your `operator<<` overload from a `const`-qualified member function as is. As @flyx said, it's a free function, so the function itself can't be `const` qualified since there's no `this` object to be treated as `const`. – Miles Budnek Jan 26 '20 at 23:16

1 Answers1

0

But operator<< is not a member - it's a free function. So there's no base object that it's not modifying.

int myFunc() const {
    return 3;
}

Also gets an error from the compiler:

error: non-member function 'int myFunc()' cannot have cv-qualifier

Your version of operator<< is also quite strange as it doesn't output anything to the stream it's supposed to, preferring instead to output things to std::cout!

I think you should reconsider what you hope to achieve, as you're trying to do something non-standard. If you just want a method that writes the contents of your class to std::cout, then just do that, rather than overloading the operator.

Note that if you had some other iostream, you'd be surprised that nothing goes into it!

std::ofstream myFile("my_path");
myFile << Player;
Arunas
  • 1,282
  • 1
  • 11
  • 17
  • The fact that it didn't *output* anything to the string was just an error... – Simo Pelle Jan 27 '20 at 12:11
  • But could I call this `function` on a constant object even if it is not declared as `const`? – Simo Pelle Jan 27 '20 at 12:12
  • you're not calling on an object - you're passing an object (reference) to it. And that parameter is declared `const` so you have declared that you will not modify it. The `const` modifier for a method says that this method will not modify the object of which it is a member. – Arunas Jan 28 '20 at 14:26
  • You might consider that `const` after a method declaration is applied to the hidden `this` parameter that is passed to every non-static method. – Arunas Jan 28 '20 at 14:29
  • @ Arunas thank you! I didn't consider the fact that I *can't* call a friend function on an object but I can *only* pass parameters to it – Simo Pelle Jan 28 '20 at 16:11
  • @Foxel, you might want to read about this in more detail here: https://en.cppreference.com/w/cpp/language/friend - note that they even discuss your use case. – Arunas Jan 29 '20 at 14:54
  • @Foxel - and if you find that the answer is correct, and helped you out of your problem, you can mark it as 'accepted' – Arunas Feb 06 '20 at 21:44