What do you think about this piece of code? How would you design the builder pattern in this situation?
#ifndef CPP_URL
#define CPP_URL
#include<iostream>
#include<vector>
#include<map>
using std::string;
enum protocol  {
  HTTP,
  HTTPS
};
static string map(protocol scheme) {
  switch(scheme) {
    case HTTP:
      return "http";
    default:
      return "https";
  }
}
static int defaultPort(protocol scheme) {
  switch (scheme) {
    case HTTP:
      return 80;
    default:
      return 440;
  }
}
class url final {
private:
  using list = std::vector<std::string>;
  using pairs = std::map<std::string, std::string>;
  const list paths;
  const pairs queries;
  const protocol scheme;
  const string domain;
  const string fragment;
  const string username;
  const string password;
  mutable int port;
public:
  class builder {
   friend url;
   private:
      protocol scheme;
      pairs queries;
      list paths;
      string domain;
      string fragment;
      string username;
      string password;
      int port = -1;
   public:
     builder& setScheme(protocol);
     builder& setFragment(const string&);
     builder& setDomain(const string&);
     builder& setUsername(const string&);
     builder& setPassword(const string&);
     builder& setPort(int port);
     builder& addQuery(const string&, const string&);
     builder& addPath(const string&);
     url& build() const;
  };
  explicit url(const url::builder&);
  string build() const;
};
using builder = url::builder;
inline builder& builder::setScheme(protocol scheme) {
  this->scheme = scheme;
  return *this;
}
inline builder& builder::setUsername(const string& username) {
  this->username = username;
  return *this;
}
inline builder& builder::setPassword(const string& password) {
  this->password = password;
  return *this;
}
inline builder& builder::setFragment(const string& fragment) {
  this->fragment = fragment;
  return *this;
}
inline builder& builder::setDomain(const string& domain) {
  this->domain = domain;
  return *this;
}
inline builder& builder::setPort(int port) {
  this->port = port;
  return *this;
}
inline builder& builder::addQuery(const string& key, const string& value) {
  queries.insert(std::pair<string, string>(key, value));
  return *this;
}
inline builder& builder::addPath(const string& path) {
  paths.insert(paths.begin(), path);
  return *this;
}
inline url& builder::build() const {
  return *(new url(*this));
}
inline url::url(const builder& object)
    : paths(object.paths)
    , queries(object.queries)
    , scheme(object.scheme)
    , domain(object.domain)
    , fragment(object.fragment)
    , username(object.username)
    , password(object.password)
    , port(object.port)
    {}
string url::build() const {
  string url = map(scheme).append("://");
  if (!username.empty()) {
    url.append(username);
    if (!password.empty()) {
      url.append(":").append(password);
    }
    url.append("@");
  }
  url.append(domain);
  if (port == -1)
    port = defaultPort(scheme);
  url.append(":").append(std::to_string(port));
  for (string path : paths) {
    url.append("/");
    url.append(path);
  }
  auto it = queries.begin();
  if (it != queries.end()) {
    url.append("?").append(it->first)
      .append("=").append(it->second);
    for(it++; it != queries.end(); it++) {
      url.append("&").append(it->first)
        .append("=").append(it->second);
    }
  }
  if (!fragment.empty()) {
    url.append("#").append(fragment);
  }
  return url;
};
#endif
This is how we can use that:
   url url = url::builder()
    .setScheme(HTTPS)
    .setDomain(YOUTUBE_DOMAIN)
    .addPath(WATCH_PATH)
    .addQuery(CATEGORY, ITEM)
    .build();
  std::cout<<url.build()<<std::endl;
