3

I have a request structure with std::vector<std::string> arguments in it. I have a std::map<std::string, std::vector<std::string> > services where key is service name and value is a vector of arguments that service responds to. arguments of different services may overlap (N services may have same or partly same arguments). I need to find all services that correspond to given request. I wonder if it would be better (from code ease or reading and request selection speed most importantly) for me to use Boost ICL instead of current for_each I use for services selection (I simply iterate over each service and look if any of its arguments are presented in request)?

myWallJSON
  • 8,264
  • 17
  • 72
  • 139

1 Answers1

3

I would go with the most readable variant. If performance is of concern, just cache the applicable services for an argument (set) into a multimap.

If I got the idea right, the following shows some c++11/boost syntactic sugars which demonstrate what I mean with readability:

#include <boost/range/numeric.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>

typedef std::vector<std::string> args_t;
typedef std::map<std::string, args_t> service_map;

struct applicable
{
    template <typename T>
        applicable(const T& args) : _args(args) { }

    bool operator()(const service_map::value_type& svc) const
    {
        for (auto& a:_args)
            if (svc.second.end() == boost::find(svc.second, a))
                return false;
        return true;
    }
  private: args_t _args;
};

int main(int argc, const char *argv[])
{
    using namespace boost::adaptors;
    static const service_map services { 
        { "A", { "1","2","3" } }, 
        { "B", { "2","3","4" } },
        { "C", { "3","4","5" } }, 
        { "D", { "4","5","6" } } 
    };

    const std::string label = "request: ";

    for (const auto& req : std::list<args_t> { {"5"}, {"4","3"}, {"1","3"} })
    {
        std::cout << boost::accumulate(req, label) << std::endl;

        for (auto& svc : services | filtered(applicable(req)))
            std::cout << "applicable: " << svc.first << std::endl;
    }
}

Of course many optimizations could be applied. But you know what they say about premature optimization :)

Output:

request: 5
applicable: C
applicable: D
request: 43
applicable: B
applicable: C
request: 13
applicable: A
sehe
  • 328,274
  • 43
  • 416
  • 565
  • 1
    Could you please explain how `for (auto& svc : services | filtered(applicable(req)))` line can be recreated vith boost for_each? – myWallJSON Jan 24 '12 at 17:39
  • @myWallJSON That's tricky! `BOOST_AUTO(svcs, services | filtered(applicable(req))); BOOST_AUTO(svc, boost::begin(svcs)); BOOST_FOREACH(svc, svcs) { /*...*/ }` comes to mind – sehe Jan 24 '12 at 18:22