Standard-layout tuple implementation I have written a simple (read: incomplete) tuple implementation that, AFAICT, does not violate the standard layout requirements. It's largely based on Nish's implementation, but I use a recursive hierarchy of nested members, rather than recursive inheritance. Unfortunately this approach necessitates recursion for element access.  But for my purposes I am willing to sacrifice compilation time for a predictable memory layout... my tuple stores elements in the "correct" order.

Aside from lengthy compilation times, are there any obvious flaws to this approach?

#include &lt;cstddef&gt;
#include &lt;type_traits&gt;

template &lt;class... Ts&gt;
struct tuple;

template &lt;class T, class... Ts&gt;
struct tuple&lt;T, Ts...&gt;
{
    T first;
    tuple&lt;Ts...&gt; rest;  
};

template &lt;class T&gt;
struct tuple&lt;T&gt;
{
    T first;
};


namespace detail {

    template &lt; ::std::size_t i, class T&gt;
    struct tuple_element;

    template &lt; ::std::size_t i, class T, class... Ts&gt;
    struct tuple_element&lt;i, tuple&lt;T, Ts...&gt; &gt;
        : tuple_element&lt;i - 1, tuple&lt;Ts...&gt; &gt;
    {};

    template &lt;class T, class... Ts&gt;
    struct tuple_element&lt;0, tuple&lt;T, Ts...&gt; &gt;
    {
        using type = T;
    };


    template &lt; ::std::size_t i&gt;
    struct tuple_accessor
    {
        template &lt;class... Ts&gt;
        static inline typename tuple_element&lt;i, tuple&lt;Ts...&gt; &gt;::type &amp; get (tuple&lt;Ts...&gt; &amp; t)
        {
            return tuple_accessor&lt;i - 1&gt;::get(t.rest);
        }

        template &lt;class... Ts&gt;
        static inline const typename tuple_element&lt;i, tuple&lt;Ts...&gt; &gt;::type &amp; get (const tuple&lt;Ts...&gt; &amp; t)
        {
            return tuple_accessor&lt;i - 1&gt;::get(t.rest);
        }
    };

    template &lt;&gt;
    struct tuple_accessor&lt;0&gt;
    {
        template &lt;class... Ts&gt;
        static inline typename tuple_element&lt;0, tuple&lt;Ts...&gt; &gt;::type &amp; get (tuple&lt;Ts...&gt; &amp; t)
        {
            return t.first;
        }

        template &lt;class... Ts&gt;
        static inline const typename tuple_element&lt;0, tuple&lt;Ts...&gt; &gt;::type &amp; get (const tuple&lt;Ts...&gt; &amp; t)
        {
            return t.first;
        }
    };


    template &lt;class T, class... Ts&gt;
    struct tuple_builder
    {
        static inline void make (tuple&lt;typename ::std::decay&lt;T&gt;::type, typename ::std::decay&lt;Ts&gt;::type...&gt; &amp; t, T &amp;&amp; x, Ts &amp;&amp;... xs)
        {
            t.first = x;
            tuple_builder&lt;Ts...&gt;::make(t.rest, ::std::forward&lt;Ts&gt;(xs)...);
        }
    };

    template &lt;class T&gt;
    struct tuple_builder&lt;T&gt;
    {
        static inline void make (tuple&lt;typename ::std::decay&lt;T&gt;::type&gt; &amp; t, T &amp;&amp; x)
        {
            t.first = x;
        }
    };

} // namespace detail



template &lt;class... Ts&gt;
inline tuple&lt;typename ::std::decay&lt;Ts&gt;::type...&gt; make_tuple (Ts &amp;&amp;... x)
{
    tuple&lt;typename ::std::decay&lt;Ts&gt;::type...&gt; t;
    detail::tuple_builder&lt;Ts...&gt;::make(t, ::std::forward&lt;Ts&gt;(x)...);
    return t;
}

template &lt; ::std::size_t i, class... Ts&gt;
inline typename detail::tuple_element&lt;i, tuple&lt;Ts...&gt; &gt;::type &amp; get (tuple&lt;Ts...&gt; &amp; t)
{
    return detail::tuple_accessor&lt;i&gt;::get(t);
}

template &lt; ::std::size_t i, class... Ts&gt;
inline const typename detail::tuple_element&lt;i, tuple&lt;Ts...&gt; &gt;::type &amp; get (const tuple&lt;Ts...&gt; &amp; t)
{
    return detail::tuple_accessor&lt;i&gt;::get(t);
}



static_assert(::std::is_standard_layout&lt;tuple&lt;bool, int, float, char, double, tuple&lt;int, char&gt; &gt; &gt;(), "Compiler is stupid");


For more context, see this
Minor issues:


You need to include &lt;utility&gt; for std::forward.
You don't support empty tuples. It's obviously not a huge problem, but adding one line 

template &lt;&gt; struct tuple&lt;&gt; {};


is no great burden either.
You should be using std::forward for the assignments in the make functions:

t.first = std::forward&lt;T&gt;(x);


so move assignment is used when x is an rvalue reference.


Slightly bigger issue:


Having no constructors in tuple means that your tuple can never contain a type that is not default constructible. "Default construction followed by assignment" is inherently less efficient than value construction. I would write perfect forwarding constructors for the tuple specializations, something like:

template &lt;class T, class... Ts&gt;
struct tuple&lt;T, Ts...&gt;
{
    T first;
    tuple&lt;Ts...&gt; rest;

    tuple() = default;
    template &lt;class U, class...Us, class=
      typename ::std::enable_if&lt;
        !::std::is_base_of&lt;
          tuple,
          typename ::std::decay&lt;U&gt;::type
        &gt;::value
      &gt;::type
    &gt;
    tuple(U&amp;&amp; u, Us&amp;&amp;...tail) :
      first(::std::forward&lt;U&gt;(u)),
      rest(::std::forward&lt;Us&gt;(tail)...) {}
};

template &lt;class T&gt;
struct tuple&lt;T&gt;
{
    T first;

    tuple() = default;
    template &lt;class U, class=
      typename ::std::enable_if&lt;
        !::std::is_base_of&lt;
          tuple,
          typename ::std::decay&lt;U&gt;::type
        &gt;::value
      &gt;::type
    &gt;
    tuple(U&amp;&amp; u) :
      first(::std::forward&lt;U&gt;(u)) {}
};


(All that enable_if junk is to keep the perfect forwarding constructors from being used for copy/move construction from another tuple.) This allows make_tuple to become a one-liner:

return tuple&lt;typename ::std::decay&lt;Ts&gt;::type...&gt;(::std::forward&lt;Ts&gt;(x)...);



(Code demo with suggested changes and the now-unnecessary builder templates removed)