Is it possible to use boost::filter_iterator for output?

后端 未结 1 622
甜味超标
甜味超标 2020-12-09 22:28

I am using std::transform with an std::back_inserter to append elements to an std::deque. Now the transformation may fail and will re

相关标签:
1条回答
  • 2020-12-09 23:05

    I suggest using boost range (algorithms & adaptors) for ease of use, you'd write:

    boost::copy(
        data | transformed(makeT) | filtered(validate) /* | indirected */, 
        std::back_inserter(queue));
    

    Here is a complete working example of that:

    #include <boost/range.hpp>
    #include <boost/range/adaptors.hpp>
    #include <boost/range/algorithm.hpp>
    #include <boost/optional.hpp>
    
    #include <vector>
    #include <deque>
    
    typedef boost::optional<int> T;
    typedef std::deque<T> Q;
    
    static T makeT(int i)
    {
        if (i%2) return T();
        else     return i;
    }
    
    static bool validate(const T& optional) 
    { 
        return (bool) optional; // select the optional that had a value set
    }
    
    int main()
    {
        static const int data[] =  { 1,2,3,4,5,6,7,8,9 };
    
        Q q;
    
        using boost::adaptors::filtered;
        using boost::adaptors::transformed;
    
        // note how Boost Range elegantly supports an int[] as an input range
        boost::copy(data | transformed(makeT) | filtered(validate), std::back_inserter(q));
    
        // demo output: 2, 4, 6, 8 printed
        for (Q::const_iterator it=q.begin(); it!=q.end(); ++it)
        {
            std::cout << (*it? "set" : "unset") << "\t" << it->get_value_or(0) << std::endl;
        }
    
        return 0;
    }
    

    Update

    With a little help from this answer: Use boost::optional together with boost::adaptors::indirected

    I now include an elegant demonstration of using the indirected range adaptor as well for immediate output of the queue (dereferencing the optionals):

    Note that for (smart) pointer types there would obviously be no need to provide the pointee<> specialisation. I reckon this is by design: optional<> is not, and does not model, a pointer

    #include <boost/range.hpp>
    #include <boost/range/adaptors.hpp>
    #include <boost/range/algorithm.hpp>
    
    #include <boost/optional.hpp>
    
    namespace boost {
        template<typename P> struct pointee<optional<P> > {
            typedef typename optional<P>::value_type type;
        };
    }
    
    typedef boost::optional<int> T;
    
    static T    makeT(int i)                { return i%2?  T() : i; }
    static bool validate(const T& optional) { return (bool) optional; }
    
    int main() {
        using namespace boost::adaptors;
    
        static int data[] =  { 1,2,3,4,5,6,7,8,9 };
        boost::copy(data | transformed(makeT) 
                         | filtered(validate) 
                         | indirected, 
                         std::ostream_iterator<int>(std::cout, ", "));
    }
    
    0 讨论(0)
提交回复
热议问题