Initialize const with sum of array

Hi, I want to initialize a constant (TOTAL) as follows:

1
2
3
const int N = 2;
const int MY_ARR[N]{3,4};
const int TOTAL = std::accumulate(MY_ARR, MY_ARR + N, 0);

I know that I cannot do that because the result of accumulate is not a constant expression. I have read something about constexpr, but I donĀ“t know if that is useful for my problem.
Any idea about how to write the code?

Thanks!
There is no issue with applying const to your TOTAL variable.
'const', in this context, just means 'read-only'. It's just a safety measure to communicate that you never intend to change the value of that variable.

What you can't do, however, is then use the result of TOTAL to initialize, say, the size of an array, or an enum, or a template argument, because those indeed do need to be compile-time constants. Is this what you are actually trying to do?

You could write your own C++20 equivalent with consteval:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <numeric>

template <int N>
class Foo { };

namespace util {

template <typename Iter, typename T>
consteval T accumulate(Iter begin, Iter end, T init)
{
    T sum = init;
    for (Iter it = begin; it < end; it++)
    {
        sum += *it;
    }
    
    return sum;
}

}

int main()
{
    constexpr int N = 2;
    constexpr int MY_ARR[N]{3,4};
    constexpr int TOTAL = util::accumulate(MY_ARR, MY_ARR + N, 0);

    Foo<TOTAL> foo; // example: Use in template argument
    
    std::cout << TOTAL << '\n';
}


'consteval' truly forces compile-time compilation, while constexpr does not.
(But a consteval function can only work with constexpr or stronger values.)
Last edited on
Of course you can do it.
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <numeric>

int main()
{
    const int N = 2;
    const int MY_ARR[N]{3,4};
    const int TOTAL = std::accumulate(MY_ARR, MY_ARR + N, 0);
    
    std::cout << "Total = " << TOTAL << '\n';
}

Output:
Total = 7
Using a C++ container such as a std::vector is easy to sum, using a vector's iterators.

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <vector>
#include <numeric>

int main()
{
    std::vector<int> vec { 3, 4, 8, 12 };

   const int sum { std::accumulate(vec.cbegin(), vec.cend(), 0) };

   std::cout << "The sum of the vector is " << sum <<'\n';
}
The sum of the vector is 27

An advantage of using a C++ vector is the container is run-time dynamic sized. You can add and remove elements as wanted.
Ganado wrote:
'consteval' truly forces compile-time compilation, while constexpr does not.

constexpr on functions doesn't but constexpr on variables does.

1
2
3
constexpr int N = 2;
constexpr int MY_ARR[N]{3,4};
constexpr int TOTAL = std::accumulate(MY_ARR, MY_ARR + N, 0);

Note that std::accumulate is constexpr since C++20 so you do not need to define your own. In general I would recommend defining functions using constexpr rather than consteval. That makes them more useful because they can be used with non-constexpr values as well.
Last edited on
Ooh, you're right, the following still compiles:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <numeric>

template <int N>
class Foo { };

int main()
{
    constexpr int N = 2;
    constexpr int MY_ARR[N]{3,4};
    constexpr int TOTAL = std::accumulate(MY_ARR, MY_ARR + N, 0);

    Foo<TOTAL> foo; // example: Use in template argument
    
    std::cout << TOTAL << '\n';
}

Good to know that you can force an 'upgrade' of a constexpr function.
Last edited on
Ganado
What you can't do, however, is then use the result of TOTAL to initialize, say, the size of an array, or an enum, or a template argument, because those indeed do need to be compile-time constants. Is this what you are actually trying to do?

That was actually my problem. I am going to use constexpr with C++20 as you are suggesting.
Thanks!
Topic archived. No new replies allowed.