Skip to main content
4 of 5
New code after review.
jaor
  • 111
  • 1
  • 5

URL Query params builder

My goal is to create a URL query params from std::map<std::string, std::string>. For example, we call to_query_params( {{"one","1"},{"two","2"}} ) and we get ?one=1&two=2.

Is this a good way of doing it?

std::string to_query_params(std::map<std::string, std::string> map)
{
    if (map.empty()){
        return "";
    }
    auto map_beg = std::begin(map);
    auto concat = [](const decltype(map)::value_type& a){
                        return a.first+"="+a.second;
                    };
    std::string result("?"+concat(*map_beg));
    std::for_each(std::next(std::begin(map)), 
                  std::end(map), 
                  [&](decltype(map)::value_type param){ 
                      result+="&"+concat(param); 
                  });
    return result;
}

EDIT AFTER COMMENTS

Ok, after given answers and comments I ended up with something like this:

template< typename Container >
std::string to_query_params(Container&& container)      // 1.
{
    if (container.empty()){
        return "";
    }
    std::string result;
    for( const auto& item : container ) {
        result.append("&")
              .append(std::get<0>(item))
              .append("=")
              .append(std::get<1>(item));               // 2.
    }
    assert(result.size() > 0);
    result[0]='?';
    return result;
}
  • we're independent of underlying container, be it multimap, map, vector<tuple<string,string>>, etc;
  • and we're independent of r/lvalueness of param being able to call to_query_params(generate_params());
  • as of the container - I'll opt for std::vector<std::tuple<std::string, std::string>>, as we do not need to access elements, but iterate over them, so linear memory block will be cache-friendly;
    • thank's to append we're not creating useless copies;
  • std::stringstream is hudge and heavy, and I tend to avoid it as much as I can;
jaor
  • 111
  • 1
  • 5