Reputation: 84
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.
Upvotes: 3
Views: 2604
Reputation: 393029
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:
uses_allocator
/allocator_arg_t
support)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
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.
In reply to the comments, here's a sample outlining some of the features mentioned above and in particular the use of piecewise emplacement:
#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")}
Upvotes: 6