Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum of array elements as constexpr

I'm trying to get the sum of a const int array as a constexpr so that I can use sum as the size of another array

constexpr int arr[] = {1, 2, 3};
constexpr int sum1 = std::accumulate(arr, arr + 3, 0); // not OK
int arr1[sum1];

The above does not compile as std::accumulate() does not return a constexpr. I end up have a workaround like this

template <size_t N>
constexpr int sum(int const a[])
{
    return a[N-1] + sum<N - 1>(a);
}

template <>
constexpr int sum<0>(int const a[])
{
    return 0;
}

constexpr int arr[] = {1, 2, 3};
constexpr int sum1 = sum<3>(arr);
int arr1[sum1];

Is there any simpler solution?

like image 612
paper Avatar asked Feb 14 '17 06:02

paper


People also ask

Why constexpr instead of define?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.

Can a function return constexpr?

A constexpr function is a function that can be invoked within a constant expression. A constexpr function must satisfy the following conditions: It is not virtual. Its return type is a literal type.

How do I know if a function is constexpr?

The easiest way to check whether a function (e.g., foo ) is constexpr is to assign its return value to a constexpr as below: constexpr auto i = foo(); if the returned value is not constexpr compilation will fail.

Can std :: function be constexpr?

Constexpr constructors are permitted for classes that aren't literal types. For example, the default constructor of std::unique_ptr is constexpr, allowing constant initialization.


2 Answers

+1 for the C++14 solutions, but I propose a C++11 solution based on a simple recursive constexpr function

template <typename T, std::size_t N>
constexpr T aSum (T const (&a)[N], std::size_t i = 0U)
 { return i < N ? (a[i] + aSum(a, i+1U)) : T{}; }

So it's possible to write

constexpr int arr[] {1, 2, 3};
constexpr int sum1 { aSum(arr) };

and sum1 become 6

like image 123
max66 Avatar answered Oct 12 '22 01:10

max66


Since C++14's relaxed constexpr you can do something like this:

#include <iostream>

constexpr int arr[] = {1, 2, 3};

template <size_t Size>
constexpr int sum(const int (&arr)[Size])
{
    int ret = 0;
    for (int i = 0; i < Size; ++i)
        ret += arr[i];
    return ret;
}

int main()
{
    int arr1[sum(arr)];
    std::cout << sizeof(arr1) / sizeof(int);
}
like image 33
w1ck3dg0ph3r Avatar answered Oct 12 '22 02:10

w1ck3dg0ph3r