1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
#include <iostream>
#include <concepts>
#include <random>
#include <ranges>
#include <string>
#include <string_view>
#include <deque>
namespace utility
{
template < std::integral INT_TYPE > INT_TYPE rand( INT_TYPE minv, INT_TYPE maxv ) // invariant: minv <= maxv
{
static std::mt19937 rng( std::random_device{}() ) ; // TO DO: warm up the twister if required
static std::uniform_int_distribution<INT_TYPE> distrib ; // initiaised once
using param_type = decltype(distrib)::param_type ;
distrib.param( param_type{ minv, maxv } ) ; // so we need to reset the parameters on each call
return distrib(rng) ;
}
template < std::ranges::random_access_range RANGE >
decltype(auto) pick_one_from( const RANGE& range ) // invariant: !std::ranges::empty(range)
{
return std::ranges::begin(range) [ rand( std::ranges::range_size_t<RANGE>(0), std::ranges::size(range) - 1 ) ] ;
}
}
int main() // usage example
{
std::cout << utility::rand( -8'000'000'000'000LL, 0LL ) << '\n' ;
const std::string_view names [] { "Bob", "Mike", "Sam", "Tom", "Dick", "Harry" };
std::cout << utility::pick_one_from(names) << '\n' ;
const std::deque<int> numbers {1,6,8,0,3,7,5,4,9,2} ;
std::cout << utility::pick_one_from(numbers) << '\n' ;
}
| |