#include <iostream>
#include <vector>
#include <algorithm>
class SquarePushBackIterator: public std::iterator<std::output_iterator_tag,int>
{
std::vector<int>& dst;
public:
SquarePushBackIterator(std::vector<int>& dst) : dst(dst) {}
// These just return references to the iterator.
// The only operation that matters is assignment.
SquarePushBackIterator& operator*() { return *this; }
SquarePushBackIterator& operator++() { return *this; }
SquarePushBackIterator& operator++(int) { return *this; }
// The assignment squares and inserts into the destination.
void operator=(int val)
{
dst.push_back(val * val);
}
};
void mergeSortedArray(std::vector<int>& data)
{
// Find the iterator range for the positive values.
using iter = std::vector<int>::const_iterator;
iter endPositive = std::end(data);
iter loopPositive = std::find_if(std::begin(data), std::end(data),
[](int val) {return val >= 0; });
// Find the iterator range for the negative values.
using reve = std::reverse_iterator<iter>;
reve endNegative = reve(std::begin(data));
reve loopNegative = reve(loopPositive);
// Create an array to put the results into.
std::vector<int> result;
result.reserve(data.size());
// Perform a standard merge
std::merge(loopPositive, endPositive, loopNegative, endNegative,
SquarePushBackIterator(result),
[](int val1, int val2){return std::abs(val1) < std::abs(val2); });
// Use move assignment to put the result in the output vector.
// Alternatively we could return an array by value.
data = std::move(result);
}
int main()
{
std::vector<int> arr={ -3, -2, 0, 4, 5, 8 };
mergeSortedArray(arr);
for (const auto& i : arr)
{
std::cout << i << ' ';
}
}