What is the correct way to deal with (otherwise) constant functions that include a random generator call of C++11's random-class? Should you prefer giving up the constant flag of the function or would it be better to declare generator and distribution as mutable elements of your class? A minimal example (not compiling) might be:
#include <random>
class foo
{
std::mt19937 MyGenerator;
std::normal_distribution<precision_type> gauss;
double get_rnd() const {return gauss(MyGenerator);}
};
The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it.
In some programming languages, const is a type qualifier (a keyword applied to a data type) that indicates that the data is read-only.
The const keyword allows you to specify whether or not a variable is modifiable. You can use const to prevent modifications to variables and const pointers and const references prevent changing the data pointed to (or referenced).
It really depends on what semantics you give to const
member access.
For Standard classes, it is thread-safe to concurrently invoke const
members from multiple threads. Leaving members const
that mutate an RNG would break that, unless the RNG is fully thread-safe (for non-const
use).
You don't have to design your classes the same way, but other developers will probably find it confusing to discover classes that can't be safely "read" (invoke const
member functions) concurrently.
One option would be to provide two variations -- a non-const version that uses the internally stored RNG, and a const
version that accepts an RNG by non-const reference. (The first can call the second, no const_cast
required). This implements the "pay only for what you need" guideline w.r.t thread-safety, as multiple threads can safely use the object if each provides a thread-local RNG instance. It also allows testing using a mock RNG implementation, which is likely even more valuable.
It really depends on what you want to achieve, typical strategies include:
Exposing mutability. Simply do not mark the method as const
.
Externalising to expose mutability. Pass the mutable elements (here the generator and distribution) as method parameters, exposing the use of mutability inside, the caller is responsible for any thread-safety implication.
Implementing "logical" constness. If the use of randomness is not considered as breaking the logical constness of the class, you can simply declare the generator and distribution as mutable
; beware of thread-safety implications (if necessary, ie in a multi-threaded application, use a mutable
mutex)
Which alternative you pick depends on the semantics you which to achieve.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With