random: choose should return iterators/pointers

This commit is contained in:
Danny Robson 2019-05-26 10:11:01 +10:00
parent 0d7c2628f3
commit 14e1e7e7c1

View File

@ -160,19 +160,30 @@ namespace cruft::random {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/// choose a value at random from an array /// Choose a value at random from an array
///
/// We return pointers (rather than values) so that we can return values
/// for empty containers without invalid dereferences.
///
/// \return A pointer to the chosen value.
template <typename T, size_t N> template <typename T, size_t N>
T& T*
choose (T (&t)[N]) choose (T (&t)[N])
{ {
std::uniform_int_distribution<size_t> dist (0, N - 1); std::uniform_int_distribution<size_t> dist (0, N - 1);
return t[dist (generator ())]; return &t[dist (generator ())];
} }
//------------------------------------------------------------------------- ///------------------------------------------------------------------------
/// Choose a value at random from a container.
///
/// We return iterators (rather than values) so that we can return values
/// for empty containers without invalid dereferences.
//
/// \return An iterator to the chosen value.
template <typename ContainerT, typename GeneratorT> template <typename ContainerT, typename GeneratorT>
auto typename ContainerT::iterator
choose (ContainerT &data, GeneratorT &&gen) choose (ContainerT &data, GeneratorT &&gen)
{ {
if (data.empty ()) if (data.empty ())
@ -188,9 +199,15 @@ namespace cruft::random {
} }
//------------------------------------------------------------------------- ///------------------------------------------------------------------------
/// Choose a value at random from a container.
///
/// We return iterators (rather than values) so that we can return values
/// for empty containers without invalid dereferences.
///
/// \return An iterator to the chosen value.
template <typename ContainerT> template <typename ContainerT>
auto typename ContainerT::iterator
choose (ContainerT &data) choose (ContainerT &data)
{ {
return choose (data, generator ()); return choose (data, generator ());