Correct alternative to a 'mutable function' in c++
I think your problem is a semantic, not a syntactic one.
Requesting the result without calling run()
first is an error, in my eyes, and should result in an exception.
If it is not an error and should indeed be possible, I see no sense in having run()
in the first place, so just drop it and do all the work in the (non-const) get_result()
.
make run() const, and make m_data and m_completed mutable. This works but is conceptually wrong because run() demonstrably changes data.
Not true, actually. The variables within your class are, in fact, altered but you could never, ever demonstrate this. Calling run() does not change anything that the user is able to retrieve from your class's interface. If you can't retrieve any information about such a change then you can't possibly demonstrate that change. This is more than a semantic issue, it speaks directly to the whole point of the 'mutable' keyword.
The 'mutable' keyword is greatly misunderstood.
That said, though with the minimally given information I have I might do it the above way, I'm not recommending it. There's almost certainly a better method that would be apparent given a larger view of your problem.
The other method I might use is what you're apparently set on avoiding: force the user to call run() before using get_data(). To tell the truth though, this is a really suboptimal method too. Perhaps more so.
Edit:
If you do decide to use the mutable method then I'd suggest some changes. Having a function called 'run()' that is const and returns nothing of interest would be quite confusing. This function should certainly be non-const. Thus, what I would do, given a decision to do it this way already, is have run() call a const and private function that has the behavior of the current 'run()' function, which is also referred to by get_data() under the specified conditions.
Just make it an error (part of the interface) to get the result prior to running the algorithm. Then you separate the work from the results, allowing both to properly indicate their constness. The get method can throw if you attempt to call it prior to running the algorithm to indicate to the client they're doing something wrong.
Some abstract remarks which may help you clarify things:
const
methods are those which don't modify the conceptual "state" of an objects,- non-
const
method are those which do. - Additionally,
mutable
fields are those which are per-object, but not considered a part of the object's conceptualstate
(like some cached values which are evaluated lazily and remembered).
The problem might be that operate_on_data
may not really be a well-defined class. What is an object of class "operate_on_data"? What is the "state" of this object? What is not? This sounds awkward (at least to me) - and awkward-sounding description of some design may indicate counter-intuitive design.
My thought is that you're keeping the different concepts of an "operation" and an "operation result" in one strange class, which leads to confusion.