I think you should clarify what you want. Depending on that the anwser will be slightly different.

Do you want an iterator to a random element than @Kerndogs 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));
    }

Not 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 CPOs so you should call them qualified and do not need to use ADL as that is already inside the mechanics of the CPO