Search code examples
c++c++11exponential-distribution

Is there a documented way to reset the lambda parameter on an existing std::exponential_distribution object?


When I look at the documentation for std::exponential_distribution, it does not seem to expose a standard way for changing the lambda parameter at runtime.

There is a param method, but it takes the opaque member type param_type, and the only documented way of obtaining an object of this type is to call param with no arguments, but that would imply a different instance must have first been created with that parameter.

Below, I show two non-documented ways of resetting lambda that compile, but I do not know whether they will result in correct behavior at runtime.

#include <random>
#include <new>

int main(){
    std::random_device rd;
    std::mt19937 gen(rd());
    std::exponential_distribution<double> intervalGenerator(5);

    // How do we change lambda after creation?
    // Construct a param_type using an undocumented constructor?
    intervalGenerator.param(std::exponential_distribution<double>::param_type(7));

    // Destroy and recreate the distribution?
    intervalGenerator.~exponential_distribution();
    new (&intervalGenerator) std::exponential_distribution<double>(9);
}

Is there a documented way to do this, and if not, are either of the two solutions safe to use?


Solution

  • Just assign a new generator to the old instance:

    std::exponential_distribution<double> intervalGenerator(5);
    intervalGenerator = std::exponential_distribution<double>(7);
    

    Portable, easy to read and obviously correct.


    Also,

    intervalGenerator.param(std::exponential_distribution<double>::param_type(7));
    

    is safe as described in 26.5.1.6/9 in both N3337 and N4141, so you can use that too. But with the first variant, no portability questions arise to begin with.