I want to simulate, in C++, the fact that in a form with drop down (or combo boxes), you can filter by selecting items and then projecting on a given set of properties for these item.In a SQL-like query it could be:select age, name from (select * from table t where isoncodereview = true)where country = US;I have come up with a template class with template parameters:K : is a  for which less is implemented (an int for example)T : is the item type which should be able to fit in a standardcollectionpredicateFilter : follow the same rules as UnaryPredicate for std::copy_ifProjection : follow the same rules as UnaryOperation for std::transformThe complete declaration of the class is:template<class K, class T> class IterativeSettingFilter{public:    IterativeSettingFilter(){}    std::vector<T>& originalSet()    {        return _origset;    }    const std::vector<T>& currentSet() const    {        return history.empty() ? _origset : history.back().second;    }    void reset()    {        history.clear();        indexByKey.clear();    }    template <class predicateFilter>    bool applyCondition(const K& id, const predicateFilter& customfilter)    {        std::vector<T> nextSet;        std::copy_if(currentSet().begin(), currentSet().end(), std::back_inserter(nextSet), customfilter);        indexByKey.insert( std::make_pair(id, history.size()) );        history.push_back(std::make_pair(id, nextSet));        return true;    }    std::vector<T> setAt(const K& id) const    {        auto it = indexByKey.find(id);        if(it == indexByKey.end())            return std::vector<T>();        size_t index = it->second;        return history[index];    }    bool rollBackBeforeCondition(const K& id)    {        if(id == defaultid)        {            reset();            return true;        }        auto it = indexByKey.find(id);        if(it == indexByKey.end())            return false;        size_t index = it->second;        while( !history.empty() && history.size() > index)//size might be linear with list before c++11        {            indexByKey.erase(history.back().first);            history.pop_back();        }        return true;    }    template <class E, class Projection>    std::set<E> project(const Projection& projection) const    {        std::set<E> projected;        std::transform(currentSet().begin(), currentSet().end(), std::inserter(projected, projected.end()), projection);        return projected;    }    template <class E, class Projection>    std::set<E> project(const K& id, const Projection& projection) const    {        std::set<E> projected;        const std::vector<T>& selectedVect = correspondingSet(id);         std::transform(selectedVect.begin(), selectedVect.end(), std::inserter(projected, projected.end()), projection);        return projected;    }    K predecessor(const K& id) const    {        auto iter = indexByKey.find(id);        if( iter != indexByKey.end() )        {            size_t pos = iter->second;            return pos == 0 ? defaultid : history.at(pos - 1).first;        }        else        {            return history.empty() ? defaultid : history.back().first;        }    }private:    const std::vector<T>& correspondingSet(const K& id) const    {        if(id == defaultid )        {            return  _origset;        }        else        {            auto iter = indexByKey.find(id);            if( iter != indexByKey.end() )            {                size_t pos = iter->second;                return history.at(pos).second;            }            else            {                return currentSet();            }        }    }private:    K defaultid;    std::vector<T> _origset;    std::vector< std::pair< K, std::vector<T> > > history;    std::map< K, size_t > indexByKey;public:    // http://en.cppreference.com/w/cpp/concept/Swappable    void swap(IterativeSettingFilter& other)     {        swap(defaultid, other.defaultid);        swap(_origset,  other._origset);        swap(history,   other.history);        swap(indexByKey,other.indexByKey)    }};You can apply as many filters to obtain an ordered list of generations. For any generation, you can project on a given property to obtain a unique set. Can I improve the performance, clarity or design? Are there better standard collections than the one I've used?
Template container simulating SQL select and where
c++;performance;c++11;simulation;template meta programming