I want to set the keys of a std::map
using the elements of a std::set
(or a std::vector
).
Something like the following...
std::set<int> keys = { 3,4,6 };
std::map<int,string> results(keys); // syntax error
Can this be done without explicitly iterating over the set?
You can't. A map
is not a set
. They're fundamentally different containers, even if the underlying structure is similar.
That said, anything's possible. The range constructor of std::map
is linear time if the elements of the range are already sorted, which set
guarantees for us. So all you need to do is apply a transformer to every element to produce a new range. The simplest would be to just use something like boost::make_transform_iterator
(or roll your own):
template <class K, class F
class V = decltype(std::declval<F&>()(std::declval<K const&>()))::second_type>
std::map<K, V> as_map(std::set<K> const& s, F&& f) {
return std::map<K,V>(
boost::make_transform_iterator(s.begin(), f),
boost::make_transform_iterator(s.end(), f));
}
std::map<int,string> results =
as_map(keys, [](int i){
return std::make_pair(i, std::string{});
});
which if you always will want default initialization, can just reduce to:
template <class V, class K>
std::map<K, V> as_map_default(std::set<K> const& s) {
auto f = [](K const& k) { return std::make_pair(k, V{}); }
return std::map<K,V>(
boost::make_transform_iterator(s.begin(), f),
boost::make_transform_iterator(s.end(), f));
}
std::map<int,string> results = as_map_default<string>(keys);