7

let us assume I have a class with

#include <iostream>
using namespace std;

class Test{
    public:
        friend istream& operator >> (istream& input, Test& test){
            input >> test.dummy;
            return input;
        };
        friend ostream& operator << (ostream& output, Test& test){
            output << test.dummy << endl;
            return output;
        };
    private:
        const int dummy;
}

This does not work because dummy is constant. Is there a way to load from file and recreate an object with parameters which are constant?

3
  • May be delete the previous object. create another object and make the previous one point to it.
    – Minato
    Commented Oct 15, 2015 at 9:01
  • 1
    The ostream operator should take a Test const& since you don't change the test class inside it.
    – user673679
    Commented Oct 15, 2015 at 9:10
  • 1
    Can you add some explanation about why dummy is const and what you're using the operator>> for in you code? Commented Oct 15, 2015 at 10:52

4 Answers 4

8

The "I really, really need this" way

Use const_cast. Usually you use it for objects that outside look like if they are constant, but internally they do need to update state every now and then. Using it for reading from stream is a little confusing, to say the least.

friend istream& operator >> (istream& input, Test& test){
    input >> const_cast<int&>(test.dummy);
    return input;
};

The recommended way

Ditch stream operator, use a factory function.

static Test fromStream(istream& input) {
    int dummy;
    input >> dummy;
    return Test(dummy);
}

The best way

Ditch const. Instead, pass your entire object as const if needed.

2

You can't. Streams are something you read from, they are not factories or something like that.

You have several choices, though:

  • Read from the stream to a non-const, and then use that to initialize your const object

  • You can make dummy non-const, initialize your object as unread, and then read into dummy; then you can pass outside only const& to dummy

4
  • 1
    The second suggestion is terrible. Commented Oct 15, 2015 at 9:30
  • @BartekBanachewicz Why?
    – Paolo M
    Commented Oct 15, 2015 at 9:35
  • 1
    Because constructing objects in invalid state is a common source of problems and goes against modern C++ best practices. Commented Oct 15, 2015 at 10:03
  • @BartekBanachewicz You right, but I've not said invalid; I was meaning something along the line of bool read = false; :) From the OP code, I can't know how Test will be used. Test may signal another thread when read, or send a message, or simply change its internal state. Though, I have to admit I've been not very clear, so -1 is welcome
    – Paolo M
    Commented Oct 15, 2015 at 10:11
2

You declared dummy const, so obviously mutating it during the lifetime of Test would break the contract about const.

This is what operator>> is doing at the moment and the compiler is helpfully trying to prevent you from breaking that contract.

Does operator>> actually do the initialization of Test?

If operator>> should only do the initialization, not overwriting, of Test, then you should turn operator>> into a factory function, as demonstrated in gwiazdorrr's "recommended way".

If, on the other hand, operator>> should overwrite Test, then you're breaking the contract about the constness of dummy, and that's just bad. Therefore, dummy should be non-const.

Does dummy really need to be const?

You could simply enforce the immutability of dummy through the interface of Test. Though in this case it could still be mutated inside the class, which is probably what you're trying to avoid.

1

Define a Dummy class:

class Dummy {
public:
    Dummy() { value = 0; }
    friend istream& operator >> (istream& input, const Dummy& dummy){
        input >> dummy.value;
        return input;
    }
    friend ostream& operator << (ostream& output, const Dummy& dummy){
        output << dummy.value << endl;
        return output;
    }
    int getValue() const { return value; }
private:
    mutable int value;
};

And use it in Test:

class Test {
public:
    Test() { cin >> dummy; }
private:
    const Dummy dummy;
};

It works as expected.

2
  • @user673679 I see I didn't make myself clear, see the edit.
    – yzn-pku
    Commented Oct 15, 2015 at 9:24
  • I see that mutable does the trick here. This is also a valid possibility.
    – varantir
    Commented Nov 18, 2015 at 13:59

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.