Loading...
Loading...
Write C++ code following Sean Parent's "No Raw Loops" philosophy. Emphasizes algorithm-based thinking, composition over iteration, and treating code as mathematical reasoning. Use when refactoring or writing new C++ to maximize clarity and correctness.
npx skill4agent add copyleftdev/sk1llz parent-no-raw-loops"No raw loops."
"A goal of software engineering is to reduce code to its essence, to remove anything that doesn't contribute to the meaning."
std::find_ifforstd::transformstd::accumulatestd::partitionstd::remove_if| Need | Algorithm |
|---|---|
| Does any element satisfy P? | |
| Do all elements satisfy P? | |
| Does no element satisfy P? | |
| How many satisfy P? | |
| Need | Algorithm |
|---|---|
| Find first matching P | |
| Find first mismatch | |
| Find subsequence | |
| Binary search | |
| Need | Algorithm |
|---|---|
| Apply f to each element | |
| Fill with value | |
| Generate values | |
| Copy with filter | |
| Need | Algorithm |
|---|---|
| Sort | |
| Partition by P | |
| Rotate | |
| Remove matching P | |
// RAW LOOP: What is this doing?
std::vector<int> result;
for (const auto& item : items) {
if (item.isValid()) {
result.push_back(item.getValue() * 2);
}
}
// ALGORITHM: Intent is clear
auto result = items
| std::views::filter(&Item::isValid)
| std::views::transform([](const Item& i) { return i.getValue() * 2; })
| std::ranges::to<std::vector>();
// Or without C++20 ranges:
std::vector<int> result;
std::transform(
items.begin(), items.end(),
std::back_inserter(result),
[](const Item& i) -> std::optional<int> {
return i.isValid() ? std::optional{i.getValue() * 2} : std::nullopt;
}
);
// (Then filter nullopt... or use a custom transform_if)// RAW LOOP: Error-prone, unclear intent
for (auto it = vec.begin(); it != vec.end(); ) {
if (shouldRemove(*it)) {
it = vec.erase(it); // O(n) each time!
} else {
++it;
}
}
// ALGORITHM: O(n) total, clear intent
vec.erase(
std::remove_if(vec.begin(), vec.end(), shouldRemove),
vec.end()
);
// C++20: Even clearer
std::erase_if(vec, shouldRemove);// Move a range to a new position within a sequence
template<typename I> // I models RandomAccessIterator
auto slide(I first, I last, I pos) -> std::pair<I, I> {
if (pos < first) return { pos, std::rotate(pos, first, last) };
if (last < pos) return { std::rotate(first, last, pos), pos };
return { first, last };
}
// Usage: Move selected items to position
auto [new_first, new_last] = slide(
selection_begin, selection_end,
drop_position
);// Move all elements satisfying predicate to position
template<typename I, typename P>
auto gather(I first, I last, I pos, P pred) -> std::pair<I, I> {
return {
std::stable_partition(first, pos, std::not_fn(pred)),
std::stable_partition(pos, last, pred)
};
}
// Usage: Gather all selected items around cursor
auto [sel_first, sel_last] = gather(
items.begin(), items.end(),
cursor_position,
[](const Item& i) { return i.selected; }
);findsearchany_oftransformcopy_ifsortpartitionrotateaccumulatereduceequalmismatch