random_iterator in C++ This is a small utility that permutes a C++ standard container without modifying the container being iterated:

random_iterator.hpp

#ifndef RANDOM_ITERATOR_HPP
#define RANDOM_ITERATOR_HPP

#include &lt;initializer_list&gt;
#include &lt;random&gt;
#include &lt;vector&gt;

namespace net {
namespace coderodde {
namespace utilities {

template&lt;typename T&gt;
class random_iterator {
private:
    std::vector&lt;T&gt; vec;

public:

    template&lt;typename Iterable&gt;
    explicit random_iterator(Iterable iterable)
    {
        for (auto&amp; x : iterable)
        {
            vec.push_back(x);
        }

        std::random_device rd;
        std::mt19937 g(rd());
        std::shuffle(vec.begin(), vec.end(), g);
    }

    template&lt;typename Iterable&gt;
    explicit random_iterator(Iterable iterable, std::random_device&amp; rd)
    {
        for (auto&amp; x : iterable)
        {
            vec.push_back(x);
        }

        std::mt19937 g(rd());
        std::shuffle(vec.begin(), vec.end(), g);
    }

    explicit random_iterator(std::initializer_list&lt;T&gt;&amp; lst)
    {
        for (auto&amp; x : lst)
        {
            vec.push_back(x);
        }

        std::random_device rd;
        std::mt19937 g(rd());
        std::shuffle(vec.begin(), vec.end(), g);
    }

    explicit random_iterator(std::initializer_list&lt;T&gt;&amp; lst,
                             std::random_device&amp; rd)
    {
        for (auto&amp; x : lst)
        {
            vec.push_back(x);
        }

        std::mt19937 g(rd());
        std::shuffle(vec.begin(), vec.end(), g);
    }

    typename std::vector&lt;T&gt;::iterator begin()
    {
        return vec.begin();
    }

    typename std::vector&lt;T&gt;::iterator end()
    {
        return vec.end();
    }

    typename std::vector&lt;T&gt;::const_iterator begin() const
    {
        return vec.cbegin();
    }

    typename std::vector&lt;T&gt;::const_iterator end() const
    {
        return vec.cend();
    }
};

} // End of net::coderodde::utilities
} // End of net::coderodde
} // End of net
#endif // RANDOM_ITERATOR_HPP


main.cpp

#include "random_iterator.hpp"
#include &lt;iostream&gt;
#include &lt;set&gt;
#include &lt;vector&gt;

using namespace std;
using net::coderodde::utilities::random_iterator;

int main(int argc, const char * argv[]) {
    vector&lt;int&gt; v1 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    for (auto&amp; x : random_iterator&lt;int&gt;(v1))
        cout &lt;&lt; x &lt;&lt; " ";

    cout &lt;&lt; "\n";

    set&lt;int&gt; s1 {1, 2, 3, 4, 5};

    for (auto&amp; x : random_iterator&lt;int&gt;(s1))
        cout &lt;&lt; x &lt;&lt; " ";

    cout &lt;&lt; "\n";
}


Critique request

I would like to know, how a professional C++ programmer would implement this.
Naming

First of, what you have created is not an iterator so naming it as such is misleading. I would recommend a name but I actually think that you should redesign your class and the name I would recommend wouldn't be fit for the redesigned class so I'll wait with that until the end.

Design

In C++ as opposed to Java, when you assign an object you get a copy of the object which can be slow and it occupies extra memory for the copy. 

I believe that there are two ways that you can improve this design:


Design a proper iterator that fulfills the contract of being an Iterator. It takes some doing but when you're done you it will not copy the contents and will be generally usable. One pitfall is how to define the end of the iterator. 
Design a "view" over an existing container. This may or may not be more convenient depending on the use case.


The two ideas are kind of related but different concepts. You can store a view as a member and it makes sense but storing an iterator as a member is kind of dubious. Depending on your use case either a view or iterator is better, for this particular case I have a feeling that an iterator is better. 

Implementation sketch as an iterator

Here I'll outline a start of an implementation of a random iterator and add a utility function in_random_order which provides nice syntactic sugar for use in range based for loops. I guess you could think of in_random_order as a poor-man's temporary view. Anyway here we go:

template&lt;typename It&gt;
class random_iterator{
    using it_traits = std::iterator_traits&lt;It&gt;;
public:
    // You must always provide these for all iterators 
    // or explicitly specialise std::iterator_traits 
    // for your iterator. It's easier to just provide them here.
    using iterator_category = it_traits::iterator_category;
    using value_type = it_traits::value_type;
    using difference_type = it_traits::difference_type;
    using pointer = it_traits::pointer;
    using reference = it_traits::reference;

    // This stores one iterator to each iterator position in the original 
    // container. Any modification of the original container invalidates
    // this iterator. We could use an LCG to avoid the linear memory.
    random_iterator(It first, It last){
        while(first != last){
            its.emplace_back(first);
            ++first;
        }
        // Shuffle the its vector.
    }

    random_iterator&amp; operator ++(){
        ++it;
        return *this;
    }

    // Depending on if you want an input iterator, forward iterator, 
    // bidirectional or random access iterator you need to implement
    // various methods here. Check the concepts page linked earlier
    // for what you must provide.

    reference operator *(){
        return *(*it); // First de-ref gets original iterator
    }    

private:
    std::vector&lt;It&gt; its;
    std::vector&lt;It&gt;::iterator it;
};

template&lt;typename Iterator&gt;
class random_order{
public:
    in_random_order(Iterator f, Iterator l){
        first = f;
        last = l;
    }

    random_iterator&lt;Iterator&gt; begin(){
        return random_iterator(first, last);
    }

    random_iterator&lt;Iterator&gt; end(){
        return random_iterator(); // Figure out how to properly make end
    }

private:
    Iterator first;
    Iterator last;
};

// These functions are necessary because template argument deduction is not
// done for class templates. This is the final piece of the puzzle
// that enables the syntax below.
template&lt;typename Container&gt;
random_order in_random_order(Container&amp; c){
    return random_order&lt;Container::iterator&gt;(c.begin(), c.end());
}

template&lt;typename Iterator&gt;
random_order in_random_order(Iterator first, Iterator last){
    return random_order&lt;Container::iterator&gt;(first, last);
}


When the above is properly implemented you should be able to do:

std::vector&lt;X&gt; data;

for(auto&amp; value : in_random_order(data)){
    // stuff
}

// Or just a range:
for(auto&amp; value : in_random_order(data.begin() + 10, data.begin() + 20)){
    // stuff
}


Note that for range based for to work, the object to be iterated over must provide member methods begin and end; or there must exist specialisations of std::begin and std::end for the object that is being iterated over. 

This is why we invent the random_order class, it basically just provides the necessary boilerplate to make the fancy syntax possible in the for loop. 

In fact, if you implement different types of iterators like for example filtering iterators and suitable iterables like filter which provide the requisite begin/end methods, you can do all manners of fun stuff by nesting iterators types like for example:

for(auto&amp; : in_random_order(filter(data, 
                [](const X&amp; x) { return x.isHappy();})) {


Although you can do the same with views I'd think the syntax is a bit more cumbersome.

Note: The above code uses a vector of indexes which is undesirable for an iterator. Iterators should ideally be a lightweight objects and are often assumed to be, for example they are often passed by value. This makes code that uses the random iterator slightly inefficient. This is worth keeping in mind or looking for a solution that doesn't need a lot of memory like this implementation does.