C++ Basics: Sort Records by Multiple Keys
Use std::tie in a comparator to sort by one field and break ties with another.
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 tuple-tie-multiple-sort-keys-demo.cpp:
#include <algorithm>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
struct Job {
int priority;
std::string name;
};
int main()
{
std::vector<Job> jobs{{2, "build"}, {1, "test"}, {1, "lint"}};
std::sort(jobs.begin(), jobs.end(), [](const Job& a, const Job& b) {
return std::tie(a.priority, a.name) < std::tie(b.priority, b.name);
});
for (const auto& job : jobs) {
std::cout << job.priority << ' ' << job.name << '\n';
}
}Compile and run it. The program runs only after compilation succeeds:
g++ -std=c++20 -Wall -Wextra -Werror -pedantic tuple-tie-multiple-sort-keys-demo.cpp -o tuple-tie-multiple-sort-keys-demo &&
./tuple-tie-multiple-sort-keys-demoObserved output:
1 lint
1 test
2 buildRead the result
Priority is compared first in ascending order. For the two priority-one jobs, the name breaks the tie, placing lint before test. The priority-two job comes last.
Apply it carefully
std::tie creates a tuple of references; these temporary tuples are used while both records are alive. Keep the field order identical on both sides. The comparator must define a strict weak ordering. std::sort does not preserve input order for records equal on every selected key; use stable_sort if that matters.
The C++ working draft describes the relevant rules. This example builds in C++20 mode; the current working draft also documents later additions.
Clean up
Remove only the source and executable created here, then return to the starting directory:
rm -- tuple-tie-multiple-sort-keys-demo.cpp tuple-tie-multiple-sort-keys-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.