diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h
index 6c3b5466..31529fa0 100644
--- a/src/lol/math/vector.h
+++ b/src/lol/math/vector.h
@@ -54,7 +54,7 @@ namespace lol
 
 template<typename T, int N, int SWIZZLE>
 struct vec_t
-    /* MUST be a different base than e.g. vec_t<T,2> otherwise the unions
+    /* MUST have a different base than e.g. vec_t<T,2> otherwise the unions
      * in vec_t<T,2> with the same base will cause empty base optimisation
      * failures. */
   : public swizzle_ops::base<T, SWIZZLE>
@@ -128,6 +128,17 @@ struct vec_t<T, N, FULL_SWIZZLE>
             m_data[i] = (T)v.m_data[i];
     }
 
+    /* Explicit constructor for initializer_list. We need these ugly
+     * loops until C++ lets us initialize m_data directly. */
+    explicit inline vec_t(std::initializer_list<element> const &list)
+    {
+        auto l = list.begin();
+        for (int i = 0; i < count && l != list.end(); ++i, ++l)
+            m_data[i] = *l;
+        for (int i = list.size(); i < count; ++i)
+            m_data[i] = (T)0;
+    }
+
     /* Various explicit constructors */
     explicit inline vec_t(T X)
     {
@@ -139,7 +150,7 @@ struct vec_t<T, N, FULL_SWIZZLE>
     inline T const& operator[](size_t n) const { return m_data[n]; }
 
 private:
-    T m_data[N];
+    T m_data[count];
 };
 
 /*
@@ -190,6 +201,17 @@ struct vec_t<T,2>
     explicit inline constexpr vec_t(vec_t<U, 2, SWIZZLE> const &v)
       : x(v[0]), y(v[1]) {}
 
+    /* Explicit constructor for initializer_list. We need these ugly
+     * loops until C++ lets us initialize m_data directly. */
+    explicit inline vec_t(std::initializer_list<element> const &list)
+    {
+        auto l = list.begin();
+        for (int i = 0; i < count && l != list.end(); ++i, ++l)
+            m_data[i] = *l;
+        for (int i = list.size(); i < count; ++i)
+            m_data[i] = (T)0;
+    }
+
     /* Various explicit constructors */
     explicit inline constexpr vec_t(T X, T Y)
       : x(X), y(Y) {}
@@ -243,6 +265,8 @@ struct vec_t<T,2>
         vec_t<T,4,0x1110> const yyyx, gggr, ttts;
         vec_t<T,4,0x1111> const yyyy, gggg, tttt;
 #endif
+
+        T m_data[count];
     };
 };
 
@@ -284,6 +308,17 @@ struct vec_t<T,3>
     explicit inline constexpr vec_t(vec_t<U, 3, SWIZZLE> const &v)
       : x(v[0]), y(v[1]), z(v[2]) {}
 
+    /* Explicit constructor for initializer_list. We need these ugly
+     * loops until C++ lets us initialize m_data directly. */
+    explicit inline vec_t(std::initializer_list<element> const &list)
+    {
+        auto l = list.begin();
+        for (int i = 0; i < count && l != list.end(); ++i, ++l)
+            m_data[i] = *l;
+        for (int i = list.size(); i < count; ++i)
+            m_data[i] = (T)0;
+    }
+
     /* Various explicit constructors */
     explicit inline constexpr vec_t(T X)
       : x(X), y(X), z(X) {}
@@ -467,6 +502,8 @@ struct vec_t<T,3>
         vec_t<T,4,0x2221> const zzzy, bbbg, pppt;
         vec_t<T,4,0x2222> const zzzz, bbbb, pppp;
 #endif
+
+        T m_data[count];
     };
 };
 
@@ -509,6 +546,17 @@ struct vec_t<T,4>
     explicit inline constexpr vec_t(vec_t<U, 4, SWIZZLE> const &v)
       : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
 
+    /* Explicit constructor for initializer_list. We need these ugly
+     * loops until C++ lets us initialize m_data directly. */
+    explicit inline vec_t(std::initializer_list<element> const &list)
+    {
+        auto l = list.begin();
+        for (int i = 0; i < count && l != list.end(); ++i, ++l)
+            m_data[i] = *l;
+        for (int i = list.size(); i < count; ++i)
+            m_data[i] = (T)0;
+    }
+
     /* Various explicit constructors */
     explicit inline constexpr vec_t(T X)
       : x(X), y(X), z(X), w(X) {}
@@ -884,6 +932,8 @@ struct vec_t<T,4>
         vec_t<T,4,0x3332> const wwwz, aaab, qqqp;
         vec_t<T,4,0x3333> const wwww, aaaa, qqqq;
 #endif
+
+        T m_data[count];
     };
 };
 
@@ -1109,6 +1159,63 @@ static inline vec_t<T,N> radians(vec_t<T,N,SWIZZLE> const &a)
     return ret;
 }
 
+/*
+ * C++11 iterators
+ */
+
+template<typename T, int N, int SWIZZLE>
+class vec_const_iter
+{
+public:
+    inline vec_const_iter(vec_t<T,N,SWIZZLE> const &vec, int pos)
+      : m_pos(pos),
+        m_vec(vec)
+    { }
+
+    inline bool operator !=(vec_const_iter<T,N,SWIZZLE> const & that) const
+    {
+        return m_pos != that.m_pos;
+    }
+
+    template<int S = SWIZZLE>
+    inline typename std::enable_if<S != -1, T const &>::type
+    operator *() const
+    {
+        return m_vec[m_pos];
+    }
+
+    template<int S = SWIZZLE>
+    inline typename std::enable_if<S == -1, T const &>::type
+    operator *() const
+    {
+        return m_vec[m_pos];
+    }
+
+    inline vec_const_iter<T,N,SWIZZLE> const & operator ++()
+    {
+        ++m_pos;
+        return *this;
+    }
+
+private:
+    int m_pos;
+    vec_t<T,N,SWIZZLE> const &m_vec;
+};
+
+/* FIXME: do we need a non-const iterator? Looks almost useless to me,
+ * and a lot of hassle with swizzling. */
+template<typename T, int N, int SWIZZLE>
+inline vec_const_iter<T,N,SWIZZLE> begin(vec_t<T,N,SWIZZLE> const &a)
+{
+    return vec_const_iter<T,N,SWIZZLE>(a, 0);
+}
+
+template<typename T, int N, int SWIZZLE>
+inline vec_const_iter<T,N,SWIZZLE> end(vec_t<T,N,SWIZZLE> const &a)
+{
+    return vec_const_iter<T,N,SWIZZLE>(a, N);
+}
+
 #if !LOL_FEATURE_CXX11_CONSTEXPR
 #undef constexpr
 #endif
diff --git a/test/unit/vector.cpp b/test/unit/vector.cpp
index c0269f5c..cfa75f0c 100644
--- a/test/unit/vector.cpp
+++ b/test/unit/vector.cpp
@@ -96,6 +96,36 @@ LOLUNIT_FIXTURE(VectorTest)
         LOLUNIT_ASSERT_LESS(a2, f2);
     }
 
+    LOLUNIT_TEST(VectorInit)
+    {
+        vec2 a { 1.f, 2.f };
+        LOLUNIT_ASSERT_EQUAL(1.f, a.x);
+        LOLUNIT_ASSERT_EQUAL(2.f, a.y);
+
+        vec3 b { 1.f, 2.f, 3.f };
+        LOLUNIT_ASSERT_EQUAL(1.f, b.x);
+        LOLUNIT_ASSERT_EQUAL(2.f, b.y);
+        LOLUNIT_ASSERT_EQUAL(3.f, b.z);
+
+        vec4 c { 1.f, 2.f, 3.f, 4.f };
+        LOLUNIT_ASSERT_EQUAL(1.f, c.x);
+        LOLUNIT_ASSERT_EQUAL(2.f, c.y);
+        LOLUNIT_ASSERT_EQUAL(3.f, c.z);
+        LOLUNIT_ASSERT_EQUAL(4.f, c.w);
+
+        vec_t<float, 10> d { 1.f, 2.f, 3.f, 4.f, 5.f };
+        LOLUNIT_ASSERT_EQUAL(1.f, d[0]);
+        LOLUNIT_ASSERT_EQUAL(2.f, d[1]);
+        LOLUNIT_ASSERT_EQUAL(3.f, d[2]);
+        LOLUNIT_ASSERT_EQUAL(4.f, d[3]);
+        LOLUNIT_ASSERT_EQUAL(5.f, d[4]);
+        LOLUNIT_ASSERT_EQUAL(0.f, d[5]);
+        LOLUNIT_ASSERT_EQUAL(0.f, d[6]);
+        LOLUNIT_ASSERT_EQUAL(0.f, d[7]);
+        LOLUNIT_ASSERT_EQUAL(0.f, d[8]);
+        LOLUNIT_ASSERT_EQUAL(0.f, d[9]);
+    }
+
     LOLUNIT_TEST(VectorSwizzle)
     {
         vec3 a(1.0f, 2.0f, 3.0f);
@@ -237,6 +267,42 @@ LOLUNIT_FIXTURE(VectorTest)
         auto vb = v1 + v2;
         LOLUNIT_ASSERT(va == vb);
     }
+
+    LOLUNIT_TEST(VectorIterator)
+    {
+        vec4 v4(1.125f, 1.25f, 1.375f, 1.25f);
+
+        for (auto x : v4)
+        {
+            LOLUNIT_ASSERT_GREATER(x, 1.0f);
+            LOLUNIT_ASSERT_LESS(x, 1.5f);
+        }
+
+        for (auto &x : v4)
+        {
+            LOLUNIT_ASSERT_GREATER(x, 1.0f);
+            LOLUNIT_ASSERT_LESS(x, 1.5f);
+        }
+
+        for (auto x : v4.zywx)
+        {
+            LOLUNIT_ASSERT_GREATER(x, 1.0f);
+            LOLUNIT_ASSERT_LESS(x, 1.5f);
+        }
+
+        vec4 const &v4c = v4;
+        for (auto x : v4c)
+        {
+            LOLUNIT_ASSERT_GREATER(x, 1.0f);
+            LOLUNIT_ASSERT_LESS(x, 1.5f);
+        }
+
+        for (auto &x : v4c)
+        {
+            LOLUNIT_ASSERT_GREATER(x, 1.0f);
+            LOLUNIT_ASSERT_LESS(x, 1.5f);
+        }
+    }
 };
 
 } /* namespace lol */