diff --git a/src/action.hpp b/src/action.hpp
index c8c57b43ba213c2b1dddde94ae1295af7e080390..1006075e85e2cc9970db7b83fc59f80a4d42d5c7 100644
--- a/src/action.hpp
+++ b/src/action.hpp
@@ -10,7 +10,7 @@ inline Scalar S_2(Array<Scalar,2> Q)
 {
     Q(0u,0u) = 123;
     Q(1u,1u) = 123;
-    return 0;
+    return Scalar(0);
 }
 
 
diff --git a/src/array.hpp b/src/array.hpp
index 672fed9bd8c1deff8dc76964abd5002c44529faa..bb2bd7f6a6da269f8e4f46ed19572d2dfa41b97d 100644
--- a/src/array.hpp
+++ b/src/array.hpp
@@ -1,13 +1,19 @@
 #ifndef ARRAY_HPP_
 #define ARRAY_HPP_
 
+#include <vector>
+#include <array>
+#include <type_traits>
+#include <stdexcept>
+
+
 /*! Simple data-by-reference strided array class
  */
-template <typename Scalar, int NDim>
+template <typename Scalar, int NDim, typename Storage = std::vector<Scalar> >
 class Array
 {
 private:
-    std::vector<Scalar>& data_;
+    Storage& data_;
     std::array<size_t, NDim> shape_;
     std::array<size_t, NDim> stride_;
     size_t offset_ = 0;
@@ -17,11 +23,11 @@ public:
         : data_(array.data_), shape_(array.shape_), stride_(array.stride_), offset_(array.offset_)
         {}
 
-    Array(std::vector<Scalar>& data, const std::array<size_t, NDim> shape, const std::array<size_t, NDim> stride, const size_t offset=0)
+    Array(Storage& data, const std::array<size_t, NDim> shape, const std::array<size_t, NDim> stride, const size_t offset=0)
         : data_(data), shape_(shape), stride_(stride), offset_(offset)
         {}
 
-    Array(std::vector<Scalar>& data, const std::array<size_t, NDim> shape)
+    Array(Storage& data, const std::array<size_t, NDim> shape)
         : data_(data), shape_(shape), offset_(0)
         {
             // row-major strides
@@ -42,6 +48,8 @@ public:
     template <size_t axis>
     Array<Scalar, NDim-1> slice(size_t pos=0) const
         {
+            static_assert(axis < NDim, "invalid slice index");
+
             std::array<size_t, NDim-1> shape;
             std::array<size_t, NDim-1> stride;
             size_t offset;
@@ -56,12 +64,14 @@ public:
                 ++j;
             }
 
-            return Array<Scalar,NDim-1>(data_, shape, stride, offset);
+            return {data_, shape, stride, offset};
         }
 
     template <size_t axis>
     Array<Scalar, NDim> slice(size_t begin, size_t end) const
         {
+            static_assert(axis < NDim, "invalid slice index");
+
             std::array<size_t, NDim> shape;
             std::array<size_t, NDim> stride;
             size_t offset;
@@ -76,10 +86,10 @@ public:
                 stride[i] = stride_[i];
             }
 
-            return Array<Scalar,NDim>(data_, shape, stride, offset);
+            return {data_, shape, stride, offset};
         }
 
-    std::vector<Scalar>& data() { return data_; }
+    Storage& data() { return data_; }
     
     template <size_t axis>
     const size_t shape() const { return shape_[axis]; }
@@ -92,11 +102,19 @@ public:
     template <typename... Idx>
     size_t index(Idx... idxs) const
         {
+            static_assert(sizeof...(idxs) == NDim,
+                          "number of indices must equal the number of dimensions");
+
             const std::array<size_t, NDim> m{idxs...};
             size_t idx = offset_;
 
-            for (size_t i = 0; i < NDim; ++i)
+            for (size_t i = 0; i < NDim; ++i) {
                 idx += stride_[i] * m[i];
+#ifndef NO_BOUNDS_CHECK
+                if (m[i] >= shape_[i])
+                    throw std::out_of_range("index out of bounds");
+#endif
+            }
 
             return idx;
         }
diff --git a/src/common.hpp b/src/common.hpp
index 0aac2318cee78f2b277908273e6f3b8c6027792a..b7f4c4b95264f0f71100e934ee61e5d00d4e7596 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -1,8 +1,6 @@
 #ifndef COMMON_HPP_
 #define COMMON_HPP_
 
-#include <array>
-#include <tuple>
 #include <iostream>
 
 #include <cppad/cppad.hpp>
diff --git a/src/main.cpp b/src/main.cpp
index 9a79fdc8033e6720b5b576013a479b785b290283..e6cc131df282cd921112f5db90ca53a5936b5f03 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4,10 +4,10 @@
 
 int main()
 {
-    std::vector<double> v(2*2*2);
-    Array<double,3> Q(v,{2,2,2});
+    std::vector<ADComplex> v(2*2*2);
+    Array<ADComplex,3> Q(v,{2,2,2});
 
-    S_2(Q.slice<3>());
+    S_2(Q.slice<2>());
 
     for (size_t i = 0; i < Q.shape<0>(); ++i) {
         for (size_t j = 0; j < Q.shape<1>(); ++j) {