Home > front end >  C STD Unordered Set/Map vs Boost Unordered Set/Map
C STD Unordered Set/Map vs Boost Unordered Set/Map

Time:12-22

What are the differences between them, and when should you use each?

I have tried a few tests on an old laptop and there seems to be no significant performance difference for storing basic types like ints and longs. I think one of the main difference is boost container emplace methods dont support std::piecewise_construct and tuples, which causes additional overhead.

Edit: the stuff I'm working on already has a lot of boost features, so I'm not worried about compatibility issues with boost libraries.

CodePudding user response:

The Boost ones have some features that do not exist in the standard library. Off the top of my head:

  • Boost Hash, which is more flexible and easier to customize than specializing std::hash<> (though specializing boost::hash<> is also supported; the easier route is to implement a inline friend size_t hash_value(T const&) which will "magically" be picked up by the default hash<> implementation

  • Boost tends to support heterogeneous lookup better (look for extended find/insert signatures)

  • The ordered versions may have extra constructors to efficiently construct over known ordered sequences

  • In general Boost containers (including others from the Boost Container library) have more guarantees/options:

    • (better) support for stateful allocators (including scoped_allocator_adaptor, so with full uses_allocator/allocator_arg_t support)
    • constructors don't allocate
    • some support for incomplete types in the the template arguments
  • As far as I know piecewise construction is perfectly fine in Boost. E.g. Change notes lists for 1.48.0:

    * `emplace` used to emulate the variadic pair constructors that
      appeared in early C  0x drafts. Since they were removed it no
      longer does so. It does emulate the new `piecewise_construct`
      pair constructors - only you need to use
      `boost::piecewise_construct`. To use the old emulation of
      the variadic constructors define
    

Summary

I don't expect significant differences in performance.

Quality of implementation differences will exist. Boost's will probably be a bit slower to compile and support older compiler versions.

BONUS

In reply to the comments, here's a sample outlining some of the features mentioned above and in particular the use of piecewise emplacement:

Live On Compiler Explorer

#include <boost/unordered_map.hpp>
#include <iomanip>
#include <fmt/ranges.h>
#include <fmt/ostream.h>

struct MyKey {
    MyKey(int i, std::string s) : _i(i), _s(std::move(s)) {}

    bool operator==(MyKey const&) const = default;

  private:
    int _i;
    std::string _s;

    friend size_t hash_value(MyKey const& mk) {
        using boost::hash_value;
        size_t seed = hash_value(mk._i);
        boost::hash_combine(seed, hash_value(mk._s));
        return seed;
    }

    friend auto& operator<<(auto& os, MyKey const& mk) {
        return os << "[" << mk._i << ", " << std::quoted(mk._s) << "]";
    }
};

int main() {
    boost::unordered_map<MyKey, std::string> m;

    m.emplace(boost::unordered::piecewise_construct,
              boost::make_tuple(42, "forty-two"),
              boost::make_tuple("the answer"));

    m.emplace(std::piecewise_construct,
              std::/*make_*/tuple(43, "forty-three"),
              std::/*make_*/tuple("not the answer"));

    fmt::print("m: {}\n", m);
}

Prints

m: {([43, "forty-three"], "not the answer"), ([42, "forty-two"], "the answer")}
  • Related