I’m working on a C++ project where I have implemented a RandomEngineWrapper
class to encapsulate various random number engines using std::variant
. However, I encounter compilation errors when trying to use this wrapper in conjunction with std::visit
.
no matching function for call to 'std::variant<std::linear_congruential_engine<unsigned int, 16807, 0, 2147483647>, std::linear_congruential_engine<unsigned int, 16807, 0, 2147483647>, std::linear_congruential_engine<unsigned int, 48271, 0, 2147483647>, std::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11, 4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>, std::mersenne_twister_engine<long long unsigned int, 64, 312, 156, 31, 13043109905998158313, 29, 6148914691236517205, 17, 8202884508482404352, 37, 18444473444759240704, 43, 6364136223846793005>, std::subtract_with_carry_engine<unsigned int, 24, 10, 24>, std::subtract_with_carry_engine<long long unsigned int, 48, 5, 12>, std::discard_block_engine<std::subtract_with_carry_engine<unsigned int, 24, 10, 24>, 223, 23>, std::discard_block_engine<std::subtract_with_carry_engine<long long unsigned int, 48, 5, 12>, 389, 11>, std::shuffle_order_engine<std::linear_congruential_engine<unsigned int, 16807, 0, 2147483647>, 256> >::variant(std::linear_congruential_engine<unsigned int, 16807, 0, 2147483647>)'
no matching function for call to 'visit(generateRandomIndex<std::vector<int> >(const std::vector<int>&, ENGINE, DISTRIBUTION)::<lambda(auto:27&)>, std::linear_congruential_engine<unsigned int, 16807, 0, 2147483647>&)'
#include <random>
#include <variant>
#include <vector>
#include <iostream>
enum class ENGINE {
DEFAULT_RANDOM_ENGINE,
MINSTD_RAND0,
MINSTD_RAND,
MT19937,
MT19937_64,
RANLUX24_BASE,
RANLUX48_BASE,
RANLUX24,
RANLUX48,
KNUTH_B,
RANDOM_DEVICE
};
enum class DISTRIBUTION {
UNIFORM_INT,
};
std::random_device rd;
class RandomEngineWrapper {
private:
std::variant<
std::default_random_engine,
std::minstd_rand0,
std::minstd_rand,
std::mt19937,
std::mt19937_64,
std::ranlux24_base,
std::ranlux48_base,
std::ranlux24,
std::ranlux48,
std::knuth_b
> engine_variant;
public:
template <typename T>
RandomEngineWrapper(T&& rng) : engine_variant(std::forward<T>(rng)) {}
template <typename T>
T& get() {
return std::get<T>(engine_variant);
}
};
RandomEngineWrapper getEngine(ENGINE engine) {
switch (engine) {
case ENGINE::DEFAULT_RANDOM_ENGINE:
return RandomEngineWrapper(std::default_random_engine(rd()));
case ENGINE::MINSTD_RAND0:
return RandomEngineWrapper(std::minstd_rand0(rd()));
case ENGINE::MINSTD_RAND:
return RandomEngineWrapper(std::minstd_rand(rd()));
case ENGINE::MT19937:
return RandomEngineWrapper(std::mt19937(rd()));
case ENGINE::MT19937_64:
return RandomEngineWrapper(std::mt19937_64(rd()));
case ENGINE::RANLUX24_BASE:
return RandomEngineWrapper(std::ranlux24_base(rd()));
case ENGINE::RANLUX48_BASE:
return RandomEngineWrapper(std::ranlux48_base(rd()));
case ENGINE::RANLUX24:
return RandomEngineWrapper(std::ranlux24(rd()));
case ENGINE::RANLUX48:
return RandomEngineWrapper(std::ranlux48(rd()));
case ENGINE::KNUTH_B:
return RandomEngineWrapper(std::knuth_b(rd()));
case ENGINE::RANDOM_DEVICE:
default:
return RandomEngineWrapper(std::mt19937(rd())); // Default case
}
}
auto getDistribution(DISTRIBUTION distribution, int size) {
switch (distribution) {
case DISTRIBUTION::UNIFORM_INT:
return std::uniform_int_distribution<>(0, size - 1);
default:
return std::uniform_int_distribution<>(0, size - 1); // Default case
}
}
template <typename Container>
int generateRandomIndex(const Container& container, ENGINE engineChoice, DISTRIBUTION distributionChoice) {
auto engineWrapper = getEngine(engineChoice);
auto dist = getDistribution(distributionChoice, container.size());
int index = 0;
std::visit([&](auto& engine) {
index = dist(engine);
}, engineWrapper.get<std::default_random_engine>());
return index;
}
int main() {
std::vector<int> myVector = {1, 2, 3, 4, 5};
int index = generateRandomIndex(myVector, ENGINE::MT19937, DISTRIBUTION::UNIFORM_INT);
std::cout << "Random index: " << index << std::endl;
return 0;
}
The std::visit
call in the generateRandomIndex
function produces the error:
no matching function for call to 'visit(generateRandomIndex<std::vector<int> >(const std::vector<int>&, ENGINE, DISTRIBUTION)::<lambda(auto:27&)>, std::linear_congruential_engine<unsigned int, 16807, 0, 2147483647>&)'
Additionally, I receive an error related to the std::variant
constructor when trying to initialize RandomEngineWrapper
with various random engines.
Why am I getting these errors, and how can I correctly use std::variant and std::visit to achieve my goal of wrapping various random engines and using them to generate random indices?
###Additional Information:###
- I’m using
std::variant
to wrap different types of random number engines. - The
RandomEngineWrapper
class is designed to abstract away the details of different random engines. - I need to generate random indices in a container using a specified random engine and distribution.
Any insights into resolving these errors would be greatly appreciated.