C++ Basics: Split Records with partition_copy
Copy passing and failing records into separate vectors while keeping their original relative order.
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 partition-copy-records-demo.cpp:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
struct CheckResult {
std::string name;
bool passed;
};
int main() {
const std::vector<CheckResult> checks{
{"compile", true}, {"format", false},
{"unit-tests", true}, {"links", false}
};
std::vector<CheckResult> passing_checks;
std::vector<CheckResult> failing_checks;
std::partition_copy(checks.begin(), checks.end(),
std::back_inserter(passing_checks),
std::back_inserter(failing_checks),
[](const CheckResult& result) { return result.passed; });
std::cout << "Passing:";
for (const auto& result : passing_checks) {
std::cout << ' ' << result.name;
}
std::cout << '\n' << "Failing:";
for (const auto& result : failing_checks) {
std::cout << ' ' << result.name;
}
std::cout << '\n' << "Original count: " << checks.size() << '\n';
}Compile and run it. The second command runs only after compilation succeeds:
g++ -std=c++20 -Wall -Wextra -Werror -pedantic partition-copy-records-demo.cpp -o partition-copy-records-demo &&
./partition-copy-records-demoObserved output:
Passing: compile unit-tests
Failing: format links
Original count: 4Read the result
compile and unit-tests go to the true destination; format and links go to the false destination. Each output preserves the input order of its selected records. The original vector is unchanged because this algorithm copies rather than rearranges the input.
Apply it carefully
Keep both destinations separate from the input and from each other. Output inserters grow the vectors as needed; raw begin iterators into empty vectors would not. The predicate should inspect records without modifying them. Copying strings has a cost, so consider in-place partitioning only when modifying the source and its order is acceptable.
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 -- partition-copy-records-demo.cpp partition-copy-records-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.