编译时相当于std :: accumulate()

mad*_*uri 7 c++ templates template-meta-programming c++11 gcc4.8

我试图通过定义一个类模板来编写一个基本的编译时版本,std::accumulate()该模板将递归迭代给定的范围并在每次迭代时添加元素.

使用gcc 4.8.4on 编译测试程序时Ubuntu 14.04,出现以下错误:

compile-time-accumulate.cpp: In function ‘int main()’:
compile-time-accumulate.cpp:44:40: error: call to non-constexpr function ‘std::vector<_Tp, _Alloc>::const_iterator std::vector<_Tp, _Alloc>::cbegin() const [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const int*, std::vector<int> >; typename __gnu_cxx::__alloc_traits<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type>::const_pointer = const int*]’
                               v.cbegin(),
                                        ^
compile-time-accumulate.cpp:46:32: error: ‘class __gnu_cxx::__normal_iterator<const int*, std::vector<int> >’ is not a valid type for a template non-type parameter
                               0>::value;
Run Code Online (Sandbox Code Playgroud)

这是代码:

Run it online

#include <iostream>
#include <vector>

template
<
    typename     ResultType,
    typename     IteratorType,
    IteratorType Iterator,
    int          RangeLength,
    ResultType   InitialValue
>
struct accumulator
{
    static_assert(RangeLength > 1, "The range length must be > 1");
    static constexpr ResultType value = InitialValue
                                      + accumulator<ResultType,
                                                    IteratorType,
                                                    Iterator + 1,
                                                    RangeLength - 1,
                                                    *Iterator>::value;
};

template
<
    typename     ResultType,
    typename     IteratorType,
    IteratorType Iterator,
    //int          RangeLength,
    ResultType   InitialValue
>
struct accumulator<ResultType, IteratorType, Iterator, 1, InitialValue>
{
    static constexpr ResultType value = InitialValue + *Iterator;
};


int main()
{
    std::vector<int> v = {4,5,6,7};

    const int a = accumulator<int,
                              decltype(v.cbegin()),
                              v.cbegin(),
                              4,
                              0>::value;

    std::cout << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

所以基本上,标准不允许在模板参数中使用变量,这就是我在这里所做的:

const int a = accumulator<int,
                          decltype(v.cbegin()),
                          v.cbegin(),
                          4,
                          0>::value;
Run Code Online (Sandbox Code Playgroud)

问:编写类模板(或任何其他"编译时"计算机制)以获得类似结果的正确方法是什么std::accumulate()

(理想情况下,应该能够传递自定义范围和二进制操作,如真实的std::accumulate())

编辑:std::vector代码中使用仅仅是一个例子.我也尝试过std::array和C风格的阵列,但我仍然有类似的问题.

EDIT2:我不想使用宏.

编辑3:我不想使用外部库.这里的目标是做一个简单的,自包含的编译时计算块.类模板是我的第一个想法,但我对其他建议/技术持开放态度.

101*_*010 6

std::vector的存储空间是在运行时分配的.因此,在编译期间无法遍历std :: vector.

现在为std::array和原始数组.如果您的std::array变量是a,constexpr您可以使用以下构造来累积它:

template<typename T, std::size_t N>
constexpr T compile_time_accumulator(std::array<T, N> const &A, int const i = 0) {
  return (i < N)? A[i] + compile_time_accumulator(A, i + 1) : T(0);
}
Run Code Online (Sandbox Code Playgroud)

现场演示

对于原始数组,还提供了它们的声明constexpr,以下结构:

template<typename T, std::size_t N>
constexpr T compile_time_accumulator(T const (&A)[N], int const i = 0) {
  return (i < N)? A[i] + compile_time_accumulator(A, i + 1) : T(0);
}
Run Code Online (Sandbox Code Playgroud)

现场演示

现在在C++中,14件事情constexpr更加轻松,您可以执行以下操作:

template<typename T, std::size_t N>
constexpr T compile_time_accumulator(T const (&A)[N]) {
  T sum(T(0));

  for(int i = 0; i < N; ++i) {
    sum += A[i];
  }

  return sum;
}
Run Code Online (Sandbox Code Playgroud)

现场演示

要么

template<typename T, std::size_t N>
constexpr T compile_time_accumulator(std::array<T, N> const &A) {
  T sum(T(0));

  for(int i = 0; i < N; ++i) {
    sum += A[i];
  }

  return sum;
}
Run Code Online (Sandbox Code Playgroud)

现场演示