Compile-time list in C++ Everything is evaluated in compile-time. You will need a C++14 compiler. The compilation time is quite long, and with a bigger list input, you'll get some error messages like constexpr evaluation hit maximum step limit.

#include &lt;iostream&gt;
#include &lt;limits&gt;
#include &lt;initializer_list&gt;

template&lt;typename T&gt;
class List
{
  template&lt;typename T2&gt;
  friend std::ostream &amp;operator&lt;&lt;(std::ostream &amp;, const List&lt;T2&gt; &amp;);
public:
  constexpr List();
  constexpr List(std::initializer_list&lt;T&gt;);
  constexpr T head() const;
  constexpr List&lt;T&gt; tail() const;
  constexpr List&lt;T&gt; add(T) const;
  constexpr List&lt;T&gt; merge(List&lt;T&gt;) const;
  constexpr List&lt;T&gt; reverse() const;
  template&lt;typename Filter&gt;
  constexpr List&lt;T&gt; filter(Filter) const;
  constexpr List&lt;T&gt; sort() const;
  constexpr T sum() const;
private:
  int length;
  T array[std::numeric_limits&lt;int&gt;::max() &gt;&gt; 2];
};

template&lt;typename T&gt;
constexpr List&lt;T&gt;::List()
: length {0}
, array {0}
{
}

template&lt;typename T&gt;
constexpr List&lt;T&gt;::List(std::initializer_list&lt;T&gt; l)
: length {static_cast&lt;int&gt;(l.size())}
, array {0}
{
  for (auto it = l.begin(); it != l.end(); ++it)
  {
    array[it - l.begin()] = *it;
  }
}

template&lt;typename T&gt;
constexpr T List&lt;T&gt;::head() const
{
  return array[0];
}

template&lt;typename T&gt;
constexpr List&lt;T&gt; List&lt;T&gt;::tail() const
{
  List&lt;T&gt; l;
  l.length = length - 1;
  for (int i = 0; i &lt; l.length; ++i)
  {
    l.array[i] = array[i + 1];
  }
  return l;
}

template&lt;typename T&gt;
constexpr List&lt;T&gt; List&lt;T&gt;::add(T t) const
{
  List&lt;T&gt; l {*this};
  l.array[l.length++] = t;
  return l;
}

template&lt;typename T&gt;
constexpr List&lt;T&gt; List&lt;T&gt;::merge(List&lt;T&gt; l) const
{
  for (int i = l.length - 1; i &gt;= 0; --i)
  {
    l.array[i + length] = l.array[i];
  }
  for (int i = 0; i &lt; length; ++i)
  {
    l.array[i] = array[i];
  }
  l.length += length;
  return l;
}

template&lt;typename T&gt;
constexpr List&lt;T&gt; List&lt;T&gt;::reverse() const
{
  List&lt;T&gt; l;
  l.length = length;
  for (int i = 0; i &lt; l.length; ++i)
  {
    l.array[i] = array[length - i - 1];
  }
  return l;
}

template&lt;typename T&gt;
template&lt;typename Filter&gt;
constexpr List&lt;T&gt; List&lt;T&gt;::filter(Filter f) const
{
  List&lt;T&gt; l;
  for (int i {0}; i &lt; length; ++i)
  {
    if (f(array[i]))
    {
      l = l.add(array[i]);
    }
  }
  return l;
}

template&lt;typename T&gt;
struct LT
{
  T pivot;
  constexpr bool operator()(T t) const
  {
    return t &lt; pivot;
  }
};

template&lt;typename T&gt;
struct GE
{
  T pivot;
  constexpr bool operator()(T t) const
  {
    return t &gt;= pivot;
  }
};

template&lt;typename T&gt;
constexpr List&lt;T&gt; List&lt;T&gt;::sort() const
{
  if (length == 0)
  {
    return *this;
  }
  return tail().filter(LT&lt;T&gt; {head()}).sort().add(head())
  .merge(tail().filter(GE&lt;T&gt; {head()}).sort());
}

template&lt;typename T&gt;
constexpr T List&lt;T&gt;::sum() const
{
  if (length == 0)
  {
    return T {};
  }
  return head() + tail().sum();
}

template&lt;typename T&gt;
std::ostream &amp;operator&lt;&lt;(std::ostream &amp;os, const List&lt;T&gt; &amp;l)
{
  os &lt;&lt; '{';
  for (int i {0}; i &lt; l.length - 1; ++i)
  {
    os &lt;&lt; l.array[i] &lt;&lt; ", ";
  }
  return os &lt;&lt; l.array[l.length - 1] &lt;&lt; '}';
}

inline constexpr List&lt;int&gt; range(int a, int b, int c = 1)
{
  List&lt;int&gt; l;
  while (a &lt; b)
  {
    l = l.add(a);
    a += c;
  }
  return l;
}

int main()
{
  constexpr std::size_t n = range(0, 300).reverse().sort().sum();
  std::cout &lt;&lt; n &lt;&lt; std::endl;
}
I confess to not being entirely clear as to the purpose of this code.  It seems to me that any list known at compile time could more easily and more correctly handled by other forms of preprocessing.  With that said, though, here are some comments on this code.

Think about real machines

The code for the List class currently includes this data member:

  T array[std::numeric_limits&lt;int&gt;::max() &gt;&gt; 2];


On my machine, this attempts to allocate 2GB on the stack for an int-based List. That's a rather large amount of memory to attempt to allocate for every List!  Perhaps this could be trimmed to some reasonable value. 

Reduce the number of requirements on template types

The code requires a number of operations on the underlying T type.  It requires both &lt; and &gt;= but that requirement can be relaxed somewhat by defining GE's operator like this:

constexpr bool operator()(T t) const {
    return !(t &lt; pivot);
}


Pass const references where practical

Rather than passing by value, it would probably make more sense in the general case to pass by const reference.  So for example, the previous function could be written like this instead:

constexpr bool operator()(const T &amp;t) const {
    return !(t &lt; pivot);
}


In fact, one of the only places that can't be treated this way is the argument to merge() which must be passed by value.

Try it with a non-primitive type

Whenver you're creating templated code, carefully consider just how it might be used and what requirements it may demand of the underlying type.  One technique I use is to wrap a primitive type inside a goofy minimalistic wrapper for testing:

template &lt;typename T&gt;
class Goofy
{
public:
    constexpr Goofy(T n = 0) : num(n) { } 
    constexpr Goofy(const Goofy &amp;g2) : num(g2.num) { }
    constexpr Goofy &amp;operator=(const Goofy &amp;g2) { num = g2.num; return *this; }
    constexpr Goofy &amp;operator+=(const Goofy &amp;g2) { num += g2.num; return *this; }
    constexpr bool operator&lt;(const Goofy &amp;g2) const { return num &lt; g2.num; }

    friend std::ostream &amp;operator&lt;&lt;(std::ostream &amp;out, const Goofy &amp;g2) {
        return out &lt;&lt; g2.num;
    }
private:
    T num;
};

template &lt;typename T&gt;
constexpr Goofy&lt;T&gt; operator+(const Goofy&lt;T&gt; &amp;g1, const Goofy&lt;T&gt; &amp;g2)
{
    Goofy&lt;T&gt; result(g1);
    result += g2;
    return result;
}


This represents a minimal interface that can then be tested with your template:

int main()
{
  constexpr List&lt;Goofy&lt;float&gt;&gt; list{0, 5, 8, 13, 1, 7};
  std::cout &lt;&lt; list &lt;&lt; std::endl;
  std::cout &lt;&lt; list.reverse() &lt;&lt; std::endl;
  std::cout &lt;&lt; list.sort() &lt;&lt; std::endl;
  constexpr auto m = list.sum();
  std::cout &lt;&lt; m &lt;&lt; std::endl;
}      


Sample output

{0, 5, 8, 13, 1, 7}
{7, 1, 13, 8, 5, 0}
{0, 1, 5, 7, 8, 13}
34