#include #include // With C++20 concepts #include template concept unary_operation = std::invocable && std::same_as>; template< std::input_iterator I, std::bidirectional_iterator D, unary_operation> NegateOp > requires std::same_as, std::iter_value_t> && std::regular> // Without C++20 concepts /* template */ D free_reduce(I first, I last, D out, NegateOp negate) { if (first == last) return out; D out_start = out; *out = *first; ++out; ++first; while (first != last) { if (out != out_start && negate(*first) == *(out - 1)) { --out; } else { *out = *first; ++out; } ++first; } return out; } template< std::input_iterator I, std::bidirectional_iterator D, unary_operation> NegateOp > requires std::same_as, std::iter_value_t> D word_negate(I first, I last, D d_first, NegateOp negate) { D d_last = std::transform(first, last, d_first, negate); std::reverse(d_first, d_last); return d_last; } template< std::bidirectional_iterator I, unary_operation> NegateOp > void word_negate_inplace(I first, I last, NegateOp negate) { word_negate(first, last, first, negate); } template void word_negate_inplace(I first, I last) { word_negate(first, last, first, std::negate>()); } template void print_word(I start, I end) { while (start != end) { std::cout << (*start) << " "; ++start; } std::cout << std::endl; } int main(int argc, const char* argv[]) { int word[] = { 3, -2, 1, -1, 2, 7, -1, 1, 4 }; constexpr size_t n = sizeof(word) / sizeof(int); { int out[n]; int* end_out = free_reduce(word, word + n, out, std::negate()); print_word(out, end_out); } { int out[n]; int* end_out = word_negate(word, word + n, out, std::negate()); print_word(out, end_out); } { word_negate_inplace(word, word + n); print_word(word, word + n); } return 0; }