A Slice-type for C++ The Go programming language has that slice type, which is under the hood a pointer to an actual array. This allows treating the subarrays as actual arrays with almost no performance overhead. This code snippet is about implementing slice type for C++ arrays and vectors.

slice.h:

#ifndef SLICE_H
#define SLICE_H

#include &lt;sstream&gt;
#include &lt;stdexcept&gt;
#include &lt;string&gt;

template&lt;class T&gt;
class slice {
    private:
        T*     m_array;
        size_t m_length;

    public:
        slice(T* array, size_t length) {
            this-&gt;m_array  = array;
            this-&gt;m_length = length;
        }

        slice(T* array, size_t length, size_t skip) {
            this-&gt;m_array = array + skip;
            this-&gt;m_length = length;
        }

        T&amp; operator[](size_t index) { 
            if (index &gt;= m_length) {
                std::ostringstream os;
                os &lt;&lt; "Bad index: " &lt;&lt; index &lt;&lt; ", slice size: " &lt;&lt; m_length;
                throw std::runtime_error(os.str());
            }

            return m_array[index];
        }

        size_t size() {
            return m_length;
        }

        T* begin() {
            return m_array;
        }

        T* end() {
            return m_array + m_length;
        }

        const T* begin() const {
            return m_array;
        }

        const T* end() const {
            return m_array + m_length;
        }
};

#endif  /* SLICE_H */


main.cpp:

#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;

#include "slice.h"

using std::cout;
using std::endl;
using std::vector;

int main(int argc, char** argv) {
    int int_array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    //// Should be 4, 5, 6, 7, 8.
    slice&lt;int&gt; pizza_slice = slice&lt;int&gt;(int_array, 5, 3);

    cout &lt;&lt; "Arrays slice size: " &lt;&lt; pizza_slice.size() &lt;&lt; endl;

    for (int i : pizza_slice)
    {
        cout &lt;&lt; i &lt;&lt; endl;
    }

    vector&lt;int&gt; int_vector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

    //// Should be 2, 3, 4
    pizza_slice = slice&lt;int&gt;(&amp;int_vector[0], 3, 1);

    cout &lt;&lt; "Vector slice size: " &lt;&lt; pizza_slice.size() &lt;&lt; endl;

    for (int i : pizza_slice) 
    {
        cout &lt;&lt; i &lt;&lt; endl;
    }

    return 0;
}


Any critique is much appreciated.
This looks pretty good. 

Use mem-initializer lists

When you write

slice(T* array, size_t length) {
    this-&gt;m_array  = array;
    this-&gt;m_length = length;
}


you're default constructing m_array and m_length and then assigning them. For pointers and integral types, this isn't exactly expensive, but it's a waste and may as well not get into that habit. Prefer directly constructing:

slice(T* array, size_t length)
: m_array(array)
, m_length(length)
{ }


Your other constructor can on the one hand just delegate to this one:

slice(T* array, size_t length, size_t skip)
: slice(array + skip, length)
{ }


but on the other hand doesn't really need to exist anyway. Just let the user pass in where he wants to start. This strikes me as just bloaty. 

const functions

size() should be const, and you're missing T const&amp; operator[](size_t) const. 

You could also provide a T* data() and T const* data() const, which in this case just alias begin().

Additionally, consider providing a different constructor so that I can construct a slice&lt;const T&gt; from a slice&lt;T&gt;. That's something that makes sense. 

throwing

If you're throwing due to out of range indexing, you should throw std::out_of_range. But generally, avoid having operator[] throw. This is what you're going to use most often so it's best to make it as simple as possible. If you want to provide a throwing alternative, the typical pattern followed by the standard library is to provide an at() function that does the bounds checking and then forwards along to operator[]. 

constexpr

Everything here can be constexpr. Just go overboard.