Search code examples
c++stlostreamstl-algorithm

Determine end of copied range when using remove_copy_if with ostream_iterator


I am trying to use remove_copy_if to copy an iterable directly to stdout through ostream_iterator. The remove_copy_if guarantees that the return value is an iterator to the end of the output range. This return value is useful in a way to determine the no of elements copied to the destination, by finding out the distance between the start of the output iterator and the return iterator. This makes sense when using a container but how to use the same functionality to determine the no of elements copied to the destination if its an ostream_iterator.

The following example should make more sense to what I might want to achieve

#include<vector>
#include<iterator>
#include<algorithm>
#include<functional>
#include<iostream>
#include <time.h>
using namespace std;
int  main() {
    int rawdata[] = {1,2,3,4,5,6,7,8,9,10,11};
    vector<int> data(20);
    vector<int>::iterator curr = remove_copy_if(rawdata,rawdata + sizeof(rawdata)/sizeof(rawdata[0]),data.begin(),bind2nd(greater<int>(),10));
    wcout<<L"No of data copied = "<<curr - data.begin()<<endl;
    for(int i=0;i<10;i++) {
    int some_value = rand()%20 + 1;
    ostream_iterator<int> curr = remove_copy_if(data.begin(),data.end(),ostream_iterator<int>(cout),bind2nd(less<int>(),some_value));
    //if (curr - what???? > 0) 
        cout<<endl;
    }
    return 0;
    } 

Solution

  • I came across the following non-thread safe , not so elegant solution to make this work.

    #include<vector>
    #include<iterator>
    #include<algorithm>
    #include<functional>
    #include<iostream>
    #include <time.h>
    #include <algorithm>
    using namespace std;
    template<class _Fn1>
    class counter
        : public std::unary_function<typename _Fn1::argument_type, bool>
        {   
        public:
        explicit counter(const _Fn1& _Func)
            : _Functor(_Func)   {
            count = countTrue = countFalse = 0;
    
            }
    
        bool operator()(const typename _Fn1::argument_type& _Left) const
            {   
            count++;
            if (_Functor(_Left)) {
            countTrue++;
            return true;
            } else {
                countFalse++;
                return false;
            }
            }
        static int count, countTrue,countFalse;
        protected:
    
        _Fn1 _Functor;  // the functor to apply
        };
    template<class _Fn1>
    int counter<_Fn1>::count=0,counter<_Fn1>::countTrue=0,counter<_Fn1>::countFalse=0;
    int  main() {
        int rawdata[] = {1,2,3,4,5,6,7,8,9,10,11};
        vector<int> data(20);
        vector<int>::iterator curr = remove_copy_if(rawdata,rawdata + sizeof(rawdata)/sizeof(rawdata[0]),data.begin(),bind2nd(greater<int>(),10));
        wcout<<L"No of data copied = "<<curr - data.begin()<<endl;
        for(int i=0;i<10;i++) {
        int some_value = rand()%20 + 1;
        ostream_iterator<int> curr = remove_copy_if(data.begin(),data.end(),ostream_iterator<int>(cout),counter<binder2nd<less<int>>>(bind2nd(less<int>(),some_value)));
        if (counter<binder2nd<less<int>>>::countFalse) {
        cout<<endl<<"No of data printed = "<<counter<binder2nd<less<int>>>::countFalse<<endl;
        }
        }
        return 0;
        }