title: Compile-time equivalent to std::accumulate()
body: <p>I tried to code a basic, <strong>compile-time</strong> version of <a href="http://en.cppreference.com/w/cpp/algorithm/accumulate" rel="noreferrer"><code>std::accumulate()</code></a> by defining a class template that would recursively iterate through a given range and would add the elements at each iteration.</p>
  
  <p>When compiling a test program using <code>gcc 4.8.4</code> on <code>Ubuntu 14.04</code>, I get the following error:</p>
  
  <pre><code>compile-time-accumulate.cpp: In function ‘int main()’:
  compile-time-accumulate.cpp:44:40: error: call to non-constexpr function ‘std::vector&lt;_Tp, _Alloc&gt;::const_iterator std::vector&lt;_Tp, _Alloc&gt;::cbegin() const [with _Tp = int; _Alloc = std::allocator&lt;int&gt;; std::vector&lt;_Tp, _Alloc&gt;::const_iterator = __gnu_cxx::__normal_iterator&lt;const int*, std::vector&lt;int&gt; &gt;; typename __gnu_cxx::__alloc_traits&lt;typename std::_Vector_base&lt;_Tp, _Alloc&gt;::_Tp_alloc_type&gt;::const_pointer = const int*]’
                                 v.cbegin(),
                                          ^
  compile-time-accumulate.cpp:46:32: error: ‘class __gnu_cxx::__normal_iterator&lt;const int*, std::vector&lt;int&gt; &gt;’ is not a valid type for a template non-type parameter
                                 0&gt;::value;
  </code></pre>
  
  <p>Here's the code:</p>
  
  <p><a href="http://cpp.sh/6k4e" rel="noreferrer"><kbd>Run it online</kbd></a></p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  
  template
  &lt;
      typename     ResultType,
      typename     IteratorType,
      IteratorType Iterator,
      int          RangeLength,
      ResultType   InitialValue
  &gt;
  struct accumulator
  {
      static_assert(RangeLength &gt; 1, "The range length must be &gt; 1");
      static constexpr ResultType value = InitialValue
                                        + accumulator&lt;ResultType,
                                                      IteratorType,
                                                      Iterator + 1,
                                                      RangeLength - 1,
                                                      *Iterator&gt;::value;
  };
  
  template
  &lt;
      typename     ResultType,
      typename     IteratorType,
      IteratorType Iterator,
      //int          RangeLength,
      ResultType   InitialValue
  &gt;
  struct accumulator&lt;ResultType, IteratorType, Iterator, 1, InitialValue&gt;
  {
      static constexpr ResultType value = InitialValue + *Iterator;
  };
  
  
  int main()
  {
      std::vector&lt;int&gt; v = {4,5,6,7};
  
      const int a = accumulator&lt;int,
                                decltype(v.cbegin()),
                                v.cbegin(),
                                4,
                                0&gt;::value;
  
      std::cout &lt;&lt; a &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>So basically, the standard doesn't allow the use of variables in template arguments, which is what I'm doing here:</p>
  
  <pre><code>const int a = accumulator&lt;int,
                            decltype(v.cbegin()),
                            v.cbegin(),
                            4,
                            0&gt;::value;
  </code></pre>
  
  <p><strong>Q:</strong> What is the proper method for coding a class template (or any other "compile-time" computation mechanism) for achieving a similar result to <code>std::accumulate()</code> ?</p>
  
  <p>(Ideally, one should be able pass custom ranges and binary operations like the real <code>std::accumulate()</code>)</p>
  
  <p><strong>EDIT:</strong> The <code>std::vector</code> used in the code is just an example. I've also tried <code>std::array</code> and C-style arrays but I still had similar problems.</p>
  
  <p><strong>EDIT2:</strong> I don't want to use macros.</p>
  
  <p><strong>EDIT3:</strong> I don't want to use external libraries. The goal here is to do a simple, self-contained <strong>compile-time computation</strong> block. Class template was the my first idea, but I'm open to other suggestions/techniques.</p>