Search code examples
c++visual-studiovisual-c++mersenne-twistermt19937

Visual Studio 2019 c++latest generic URNG function fails to compile after latest update


I have the following generic C++ generic URNG function:

template<class URNG> 
void TestURNG(URNG& urng)
{
    // Uniform distribution used with vector
    // Distribution is [-5, 5] inclusive
    uniform_int_distribution<long> dist(-5, 5);
    vector<long> v;
    v.resize(20);
    generate(v.begin(), v.end(), [&] { return dist(urng); });
    cout << "Randomized vector: ";
    copy(v.begin(), v.end(), ostream_iterator<long>(cout, " "));
    cout << endl;

    // Shuffle an array.
    // Notice that shuffle() takes an URNG, not a distribution
    vector<string> strings = { { "H", "He", "Li", "Be", "B", "C", "N", "O", "F",
        "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc",
        "Ti", "V", "Cr", "Mn", "Fe" } };
    shuffle(strings.begin(), strings.end(), urng);
    cout << "Randomized vector<string>: ";
    copy(strings.begin(), strings.end(), ostream_iterator<string>(cout, " "));
    cout << endl;
}

And I call the function from the following test function:

void TestRandom()
{
    // First run: non-seedable, non-deterministic URNG random_device
    // Slower but crypto-secure and non-repeatable.
    random_device device;
    cout << "Using random_device URNG:" << endl;
    TestURNG(device);

    // Second run: simple integer seed. Repeatable results
    cout << "Using constant-seed mersene twister engine URNG:" << endl;
    mt19937_64 constant_seed_mersene_twister_engine(mt19937_64(12345));
    TestURNG(constant_seed_mersene_twister_engine);

    // Third run: random_device as seed; different each run.
    // Desirable for most purposes
    cout << "Using non-deterministic-seed mersene twister engine URNG:" << endl;
    mt19937_64 non_deterministic_seed_mersene_twister_engine(mt19937_64(device()));
    TestURNG(non_deterministic_seed_mersene_twister_engine);

    // Fourth run: "warm-up" sequence as as seed; different each run.
    // Advanced uses. Allows more than 32 bits of randomness.
    cout << "Using non-deterministic-seed \"warm-up\" sequence mersene twister engine URNG" << endl;
    vector<unsigned int> seeds;
    cout << "mt19937_64::state_size: " << mt19937_64::state_size << endl;
    seeds.resize(mt19937_64::state_size);
    generate_n(seeds.begin(), mt19937_64::state_size, ref(device));
    seed_seq sequence(begin(seeds), end(seeds));
    mt19937_64 non_deterministic_seed_sequence_mersene_twister_engine(mt19937_64(sequence));
    TestURNG(non_deterministic_seed_sequence_mersene_twister_engine);
}

Using c++latest in Visual Studio 2019 results in the following compilation errors:

Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\xutility(5911,27): error C2825: '_Urng': must be a class or namespace when followed by '::' (compiling source file urng.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\algorithm(5468): message : see reference to class template instantiation 'std::_Rng_from_urng<int,_Urng0>' being compiled (compiling source file urng.cpp)
1>C:\Projects\C++\urng\urng\urng.cpp(9205): message : see reference to function template instantiation 'void std::shuffle<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>,URNG(__cdecl &)>(_RanIt,_RanIt,_Urng)' being compiled
1>        with
1>        [
1>            _Ty=std::string,
1>            URNG=std::mt19937_64 (std::mt19937_64),
1>            _RanIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<std::string>>>,
1>            _Urng=std::mersenne_twister_engine<unsigned __int64,64,312,156,31,13043109905998158313,29,6148914691236517205,17,8202884508482404352,37,18444473444759240704,43,6364136223846793005> (__cdecl &)(std::mt19937_64)
1>        ]
1>C:\Projects\C++\urng\urng\urng.cpp(9238): message : see reference to function template instantiation 'void TestURNG<std::mt19937_64(std::mt19937_64)>(URNG (__cdecl &))' being compiled
1>        with
1>        [
1>            URNG=std::mt19937_64 (std::mt19937_64)
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\xutility(5911,34): error C2510: '_Urng': left of '::' must be a class/struct/union (compiling source file urng.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\xutility(5911,1): error C2061: syntax error: identifier 'result_type' (compiling source file urng.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\xutility(5913,41): error C2065: '_Ty1': undeclared identifier (compiling source file urng.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\xutility(5913,3): error C2065: '_Ty1': undeclared identifier (compiling source file urng.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\xutility(5913,20): error C2923: 'std::conditional_t': '_Ty1' is not a valid template type argument for parameter '_Ty2' (compiling source file urng.cpp)

It used to work but recent VS2019 update caused it to fail. What do I miss?


Solution

  • Most vexing parse problem.

    You have to write:

    mt19937_64 non_deterministic_seed_sequence_mersene_twister_engine{mt19937_64(sequence)};
    

    now, you defines a function declaration.