C++ Basics: Choose the Accumulator Type Explicitly
Use the initial value to control numeric accumulation instead of accidentally truncating fractional values.
Prepare a scratch directory
Tested on Linux x86_64 with GCC 14.2.0. Install a C++20-capable compiler and standard-library development headers, with g++ on PATH. You also need Bash, a text editor, and the mktemp, rm, and rmdir utilities. No third-party library is required.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1Run the example
Save this as accumulate-initial-type-demo.cpp:
#include <array>
#include <iomanip>
#include <iostream>
#include <numeric>
int main() {
const std::array<double, 3> readings{1.5, 2.5, 3.5};
const int truncated_total = std::accumulate(readings.begin(), readings.end(), 0);
const double precise_total = std::accumulate(readings.begin(), readings.end(), 0.0);
std::cout << "Integer initial value: " << truncated_total << '\n';
std::cout << std::fixed << std::setprecision(1)
<< "Double initial value: " << precise_total << '\n';
}Compile and run it. The second command runs only after compilation succeeds:
g++ -std=c++20 -Wall -Wextra -Werror -pedantic accumulate-initial-type-demo.cpp -o accumulate-initial-type-demo &&
./accumulate-initial-type-demoObserved output:
Integer initial value: 6
Double initial value: 7.5Read the result
The initial literal 0 makes the accumulator an int. Each intermediate result is converted back to that type, producing six. The literal 0.0 selects double and retains the half-unit fractions, producing 7.5.
Apply it carefully
The return variable does not choose the internal accumulator type; the initial argument does. Pick a type with enough range as well as suitable precision. This small example keeps all conversions representable. A floating accumulator does not guarantee exact arithmetic for arbitrary decimal data, and an integer accumulator can overflow if its range is exceeded.
The C++ working draft describes the relevant library rules. This example uses only C++20 facilities, even though the linked draft also documents newer additions.
Clean up
Remove only the source and executable created here, then remove the empty practice directory:
rm -- accumulate-initial-type-demo.cpp accumulate-initial-type-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directoryIf the directory is not empty, inspect its remaining contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.