I think you should clarify what you want. Depending on that, the answer will be slightly different. If you want an iterator to a random element then Kerndog's answer is really close: template <typename Container, typename Generator> auto random_iterator(Container &con, Generator &gen) { using std::begin; using std::size; std::uniform_int_distribution<std::ptrdiff_t> dist{0, size(con) - 1}; return std::next(begin(con), dist(gen)); } template <typename Container, typename Generator> auto random_iterator(const Container &con, Generator &gen) { using std::cbegin; using std::size; std::uniform_int_distribution<std::ptrdiff_t> dist{0, size(con) - 1}; return std::next(cbegin(con), dist(gen)); } Note that there should be a const/non-const overload. If you only want the element from the container you should retrieve it or get a reference? template <typename Container, typename Generator> auto random_reference(const Container &con, Generator &gen) { using std::size; std::uniform_int_distribution<std::size_t> dist{0, size(con) - 1}; return con[dist(gen)]; } Which standard do you use? If C++20 is possible then you should use at least the `range` concept and `ranges::size`: template <range Container, typename Generator> auto random_const_iterator(const Container &con, Generator &gen) { std::uniform_int_distribution<std::ptrdiff_t> dist{0, std::ranges::size(con) - 1}; return std::next(std::ranges::cbegin(con), dist(gen)); } Note that `std::ranges::size`/`std::ranges::cbegin` are customization point objects (CPOs), so you should call them qualified; you do not need to use ADL as that is already inside the mechanics of the CPO.