Around a year ago, I wrote this Stack Overflow answer where I suggested an idea to replace deeply nested loops with a single iterable virtual-container object that contains all the indices.The following is an implementation, but I'm still not that familiar with C++11 at the moment, so I thought I'd ask for a review.Key points are...Although this seems to work in GCC, that doesn't necessarily mean I've implemented all the interfaces I need for an iterator - what have I missed?I wasn't confident about all the parameter-passing choices - where to use rvalue references, or lvalue references, pass-by-value, or letting the classes generate default methods. Have I made bad choices? Is it OK to pass std::initializer_list by value? Should loopnest_state have copy/move constructors and assignments?The elements in the container obviously don't really exist. Instead, each iterator contains a unique_ptr to a computed element value - the unique_ptr is null for end. The computed element value is mutated when the iterator is incremented, so it still references the same object, just with a new state. Is this sensible? Should I try to avoid the extra heap allocation, get rid of the unique_ptr, and build the computed value into the iterator?Anything else is welcome.class loopnest;class loopnest_iterator;class loopnest_state;class loopnest_state{  friend class loopnest_iterator;  private:    const std::vector<unsigned> &m_counts;          std::vector<unsigned>  m_indices;    unsigned m_depth;    bool step_next ()    {      m_depth = m_indices.size ();      while (m_depth > 0)      {        m_depth--;        unsigned &l_index (m_indices [m_depth]);        l_index++;        if (l_index != m_counts [m_depth])  return true;        l_index = 0UL;      }      return false;    }  public:    loopnest_state (const std::vector<unsigned> &p_counts,                    const std::vector<unsigned> &p_indices,                          unsigned               p_depth   )      : m_counts (p_counts), m_indices (p_indices), m_depth (p_depth)    {    }    loopnest_state (const std::vector<unsigned>  &p_counts,                          std::vector<unsigned> &&p_indices,                          unsigned                p_depth   )      : m_counts (p_counts), m_indices (std::move (p_indices)), m_depth (p_depth)    {    }    unsigned Outermost_Changed () const  {  return (~m_depth ? m_depth : 0);  }    unsigned Inc_Depth         () const  {  return m_depth;  }    unsigned Nest_Depth        () const  {  return m_counts.size ();  }    const std::vector<unsigned> &Indices () const  {  return m_indices;  }    unsigned size       ()           const  {  return m_indices.size ();  }    unsigned operator[] (unsigned p) const  {  return m_indices [p];  }    bool is_first () const  {  return m_depth == ~0UL;  }    bool operator== (const loopnest_state &p)    {      if (m_depth != p.m_depth) return false;      if (m_depth == ~0UL)  return true;      for (unsigned i = 0UL; i < m_indices.size (); ++i)      {        if (m_indices [i] != p.m_indices [i])  return false;      }      return true;    }    bool operator!= (const loopnest_state &p)    {      return !operator== (p);    }};class loopnest_iterator{  private:    std::unique_ptr<loopnest_state> m_state;  public:    loopnest_iterator ()    {    }    loopnest_iterator (std::unique_ptr<loopnest_state> &&p_state)      : m_state (std::move (p_state))    {    }    loopnest_iterator (loopnest_state *p_state)      : m_state (p_state)    {    }    void operator++ ()    {      if (m_state && !((*m_state).step_next ()))  m_state = nullptr;    }    bool operator== (const loopnest_iterator &p) const    {      if (m_state == p.m_state)  return true;      if ((!m_state) || (!p.m_state))  return false;      return m_state->operator== (*p.m_state);    }    bool operator!= (const loopnest_iterator &p) const    {      return !operator== (p);    }    const loopnest_state &operator*  () const  {  return *m_state;  }};class loopnest{  public:    typedef loopnest_iterator const_iterator;  private:    std::vector<unsigned>  m_counts;    //  If any count is zero, there are no cases to iterate over.    bool begin_is_end () const    {      bool l_Result = false;      for (auto i : m_counts)      {        if (i == 0)  l_Result = true;      }      return l_Result;    }  public:    loopnest ()  {}    loopnest (std::vector<unsigned> p_counts)      : m_counts (std::move (p_counts))    {    }    loopnest (std::vector<unsigned> &&p_counts)      : m_counts (std::move (p_counts))    {    }    loopnest (std::initializer_list<unsigned> p_counts)      : m_counts (p_counts)    {    }    const_iterator begin () const    {      if (begin_is_end ())  return const_iterator ();      return const_iterator (new loopnest_state (m_counts, std::vector<unsigned> (m_counts.size (), 0UL), ~0UL));    }    const_iterator end () const    {      return const_iterator ();    }};
Iterator requirements for a fake container supporting C++11 range-based for
c++;c++11;iterator