const
can mean many things. It could mean any or all of the following:
Given the same object state and parameters, the same result will happen.
The function will not change the internal state of the object on which it operates.
The function accesses the state of the object in a thread-safe way.
None of these are true for random_device::operator()
. You will get different results back; that's the whole point of the function. State that is internal to the object will be affected by requesting it (in one way or another). And the function is most assuredly not thread-safe; calling it on the same object from different threads can cause all manor of badness.
The same is true of any RNG. Getting a random number from an RNG is inherently a non-constant process. That's why the design of C++11 RNGs require the operator()
to not be declared const
.
As for your goal:
I want to make class A being properly defined (doStuff()
is a const method) and now I suddenly need to use mutable std::random_device rd;
isn't that ugly?
That depends on what you mean by const
. Obviously #2 is out, since you will be changing the mutable
state. However, you can still provide #1, for a particular definition of "same result". That is, the "stuff" that doStuff
does will be logically consistent. Not binary identical obviously, but within the bounds of the behavior of the function. That's sufficient to be const
.
And you can even provide #3, by wrapping your access to your mutable
RNG object in a mutex.
Cases like this are exactly why mutable
was invented. It's not ugly; you're simply using the feature for what it is designed for. To allow you to access some non-const
objects in a way that is logically const
to the caller.