Home > Net >  std::uniform_real_distribution cannot be const anymore in MSVS2022?
std::uniform_real_distribution cannot be const anymore in MSVS2022?

Time:08-01

In MSVS 2019 I used to declare my distribution const. Yet in the latest MSVS2022 preview, I get an error:

error C3848: expression having type 'const std::uniform_real_distribution<double>' would lose some const-volatile qualifiers in order to call 'double std::uniform_real<_Ty>::operator ()<std::mt19937>(_Engine &)'
1>        with
1>        [
1>            _Ty=double,
1>            _Engine=std::mt19937
1>        ]

If I strip the const all is fine again. Is this a MSVS2022 quirk? Or was 2019 wrong all that time? (example from https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution)

#include <random>
#include <iostream>
 
int main()
{
    std::random_device rd;  // Will be used to obtain a seed for the random number engine
    std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
    const std::uniform_real_distribution<> dis(1.0, 2.0); // this const will break in MSVS2022
    for (int n = 0; n < 10;   n) {
        // Use dis to transform the random unsigned int generated by gen into a 
        // double in [1, 2). Each call to dis(gen) generates a new random double
        std::cout << dis(gen) << ' ';
    }
    std::cout << '\n';
}

CodePudding user response:

const std::uniform_real_distribution<> was never guaranteed to be usable. The standard did not specify that operator() of std::uniform_real_distribution is const. In particular <random>'s distributions are allowed to have internal state, e.g. to remember unused bits returned from the generator or to store state if the transformation algorithm requires it.

However, standard library implementations are allowed to add const on a non-virtual member function if that wouldn't affect any call to the function that would be well-formed without it according to the standard's specification. Therefore Microsoft's implementation was not non-conforming in allowing you to use the const version, even if that is not guaranteed to work according to the standard.

Nonetheless Microsoft's standard library developers decided to remove the const by-default anyway, to encourage portability with other standard library implementations. They left the option to define _ALLOW_RANDOM_DISTRIBUTION_CONST_OPERATOR (e.g. on the command line /D_ALLOW_RANDOM_DISTRIBUTION_CONST_OPERATOR) to get back the old non-portable behavior if someone really needs it.

All of this is explained and discussed in the corresponding issue https://github.com/microsoft/STL/issues/1912 and the pull request https://github.com/microsoft/STL/pull/2732.

  • Related