我想使用std::map
(或std::set
)的元素设置std::vector
的键。
以下内容......
std::set<int> keys = { 3,4,6 };
std::map<int,string> results(keys); // syntax error
这可以在没有明确迭代集合的情况下完成吗?
答案 0 :(得分:2)
你做不到。 map
不是set
。即使底层结构相似,它们也是根本不同的容器。
那说,一切皆有可能。如果范围的元素已经排序,则std::map
的范围构造函数是线性时间,set
为我们保证。因此,您需要做的就是将变换器应用于每个元素以生成新范围。最简单的方法是使用boost::make_transform_iterator
之类的东西(或自己动手):
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{});
});
如果你总是想要默认初始化,可以简化为:
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);
答案 1 :(得分:1)
这可以在没有明确迭代集合的情况下完成吗?
没有。没有迭代它就无法知道集合中的密钥。您可以编写函数使其显示,就好像存在隐式转换一样,但这些函数必须最终迭代源集合。
一种简单的方法如下:
#include <set>
#include <map>
#include <string>
auto build_map(const std::set<int>& source) -> std::map<int,std::string>
{
std::map<int,std::string> results;
for (auto const& i : source) {
results[i];
}
return results;
}
int main()
{
std::set<int> keys = { 3,4,6 };
auto results = build_map(keys);
}
当然,如果能提高可读性,我们可能会进行调整:
#include <set>
#include <vector>
#include <unordered_set>
#include <map>
#include <string>
#include <utility>
template<class MappedType, class SourceContainer>
auto build_map(SourceContainer&& source)
{
using source_type = std::decay_t<SourceContainer>;
using key_type = typename source_type::value_type;
std::map<key_type , MappedType> results;
for (auto const& i : source) {
results[i];
}
return results;
}
int main()
{
std::set<int> keys = { 3,4,6 };
auto results = build_map<std::string>(keys);
// also
results = build_map<std::string>(std::vector<int>{3, 4, 6});
results = build_map<std::string>(std::unordered_set<int>{3, 4, 6});
}