键为无序集且值为整数对的多图 - 无法调用查找成员函数
Multimap with key as unordered set and value as integer pair - unable to call find member function
考虑代码:
#include <unordered_map>
#include <unordered_set>
#include <boost/functional/hash.hpp>
typedef std::unordered_multimap<std::unordered_set<int>, std::pair<int, int>, boost::hash<std::unordered_set<int>>> user_type_mmap;
//Essentially, above is a map, whose elements can be:
// Key: Set {1,4} -> Value: pair (4,5)
// Key: Set {1,4} -> Value: pair (4,8)
// Key: Set {2,3} -> Value: pair (8,9)
typedef std::pair<std::unordered_set<int>, std::pair<int, int>> user_type_mmap_entry;
//The above is an entry pair into the multimap
bool unorderedmultimap_val_there_already_add_if_not(user_type_mmap& uom, user_type_mmap_entry& val) {
if (uom.find(val) != uom.end()) {
return true;//val already there
}
uom.insert(val);
return false;//Value is new.
}
int main()
{
user_type_mmap uom;
std::unordered_set<int> set = { 1, 4 };
user_type_mmap_entry val = std::make_pair(set, std::pair<int, int>(4, 5));
unorderedmultimap_val_there_already_add_if_not(uom, val);
}
本质上,我定义了一个无序多图,其值键对是一个无序集(作为键)和一对整数(作为值)。
然后,函数unorderedmultimap_val_there_already_add_if_not
检查multimap中是否已经存在候选条目,如果不存在,则将其添加到multimap中。
由于函数调用 uom.find()
returns 错误:
,我在编译时遇到困难(参见 here)
error: no matching member function for call to 'find'
.
Multimaps 确实支持 find()
成员函数(参见 here),我不清楚为什么 uom.find(val)
在这种情况下失败。
正如其他人所说,你是
- 缺少哈希实现
- 使用非常低效的密钥类型
我会简化这两个帐户:
#include <boost/container/flat_set.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/functional/hash.hpp>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <fmt/ranges.h>
using Key = boost::container::flat_set<int, std::less<>,
boost::container::small_vector<int, 4>>;
using Value = std::pair<int, int>;
template <> struct std::hash<Key> {
size_t operator()(Key const& s) const { return boost::hash_range(s.begin(), s.end()); }
};
using user_type_mmap = std::unordered_multimap<Key, Value>;
using user_type_mmap_entry = user_type_mmap::value_type;
bool ensure(user_type_mmap& uom, Key key, Value val) {
if (uom.find(key) == uom.end()) {
uom.emplace(std::move(key), std::move(val));
return false;
} else {
return true;
}
}
int main(){
user_type_mmap uom{
{{2, 3}, {8, 9}},
{{3, 4}, {9, 10}},
};
fmt::print("1: {}\n", uom);
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, {4, 5}));
fmt::print("2: {}\n", uom);
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, {4, 8}));
fmt::print("3: {}\n", uom);
}
版画
1: {({3, 4}, (9, 10)), ({2, 3}, (8, 9))}
insertion: false
2: {({1, 4}, (4, 5)), ({2, 3}, (8, 9)), ({3, 4}, (9, 10))}
insertion: true
3: {({1, 4}, (4, 5)), ({2, 3}, (8, 9)), ({3, 4}, (9, 10))}
这也使得键类型在集合足够小时不使用任何动态分配。
奖金想法
您似乎是在手动将额外的密钥限制强加到标准容器中。考虑使用 MultiIndex:
#include <boost/container/flat_set.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
#include <iostream>
namespace bmi = boost::multi_index;
using Key = boost::container::flat_set<int, std::less<>,
boost::container::small_vector<int, 4>>;
template <> struct boost::hash<Key> {
size_t operator()(Key const& k) const {
return boost::hash_range(k.begin(), k.end());
}
};
struct Record {
Key key;
int a, b; // the pair
friend std::ostream& operator<<(std::ostream& os, Record const& r)
{
fmt::format_to(std::ostreambuf_iterator<char>(os), "{{ k:{} a:{} b:{} }}", r.key, r.a, r.b);
return os;
}
};
using Table = bmi::multi_index_container<
Record,
bmi::indexed_by< //
//bmi::ordered_non_unique<bmi::tag<struct byKey>,
//bmi::member<Record, Key, &Record::key>>,
bmi::hashed_non_unique<bmi::tag<struct byKeyHash>,
bmi::member<Record, Key, &Record::key>>,
bmi::ordered_unique<
bmi::tag<struct byFull>,
bmi::composite_key<Record, //
bmi::member<Record, Key, &Record::key>,
bmi::member<Record, int, &Record::a>,
bmi::member<Record, int, &Record::b> //
>>>>;
bool ensure(Table& uom, Key key, int a, int b) {
return uom.insert(Record{std::move(key), a, b}).second;
}
int main(){
Table uom{
{{2, 3}, 8, 9},
{{3, 4}, 9, 10},
};
fmt::print("1: {}\n", uom);
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, 4, 5));
fmt::print("2: {} count {{1,4}}:{}\n", uom, uom.count(Key{1, 4}));
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, 4, 8));
fmt::print("3: {} count {{1,4}}:{}\n", uom, uom.count(Key{1, 4}));
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, 4, 5));
fmt::print("4: {} count {{1,4}}:{}\n", uom, uom.count(Key{1, 4}));
}
版画
1: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }]
insertion: true
2: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }, { k:[1, 4] a:4 b:5 }] count {1,4}:1
insertion: true
3: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }, { k:[1, 4] a:4 b:8 }, { k:[1, 4] a:4 b:5 }] count {1,4}:2
insertion: false
4: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }, { k:[1, 4] a:4 b:8 }, { k:[1, 4] a:4 b:5 }] count {1,4}:2
考虑代码:
#include <unordered_map>
#include <unordered_set>
#include <boost/functional/hash.hpp>
typedef std::unordered_multimap<std::unordered_set<int>, std::pair<int, int>, boost::hash<std::unordered_set<int>>> user_type_mmap;
//Essentially, above is a map, whose elements can be:
// Key: Set {1,4} -> Value: pair (4,5)
// Key: Set {1,4} -> Value: pair (4,8)
// Key: Set {2,3} -> Value: pair (8,9)
typedef std::pair<std::unordered_set<int>, std::pair<int, int>> user_type_mmap_entry;
//The above is an entry pair into the multimap
bool unorderedmultimap_val_there_already_add_if_not(user_type_mmap& uom, user_type_mmap_entry& val) {
if (uom.find(val) != uom.end()) {
return true;//val already there
}
uom.insert(val);
return false;//Value is new.
}
int main()
{
user_type_mmap uom;
std::unordered_set<int> set = { 1, 4 };
user_type_mmap_entry val = std::make_pair(set, std::pair<int, int>(4, 5));
unorderedmultimap_val_there_already_add_if_not(uom, val);
}
本质上,我定义了一个无序多图,其值键对是一个无序集(作为键)和一对整数(作为值)。
然后,函数unorderedmultimap_val_there_already_add_if_not
检查multimap中是否已经存在候选条目,如果不存在,则将其添加到multimap中。
由于函数调用 uom.find()
returns 错误:
error: no matching member function for call to 'find'
.
Multimaps 确实支持 find()
成员函数(参见 here),我不清楚为什么 uom.find(val)
在这种情况下失败。
正如其他人所说,你是
- 缺少哈希实现
- 使用非常低效的密钥类型
我会简化这两个帐户:
#include <boost/container/flat_set.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/functional/hash.hpp>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <fmt/ranges.h>
using Key = boost::container::flat_set<int, std::less<>,
boost::container::small_vector<int, 4>>;
using Value = std::pair<int, int>;
template <> struct std::hash<Key> {
size_t operator()(Key const& s) const { return boost::hash_range(s.begin(), s.end()); }
};
using user_type_mmap = std::unordered_multimap<Key, Value>;
using user_type_mmap_entry = user_type_mmap::value_type;
bool ensure(user_type_mmap& uom, Key key, Value val) {
if (uom.find(key) == uom.end()) {
uom.emplace(std::move(key), std::move(val));
return false;
} else {
return true;
}
}
int main(){
user_type_mmap uom{
{{2, 3}, {8, 9}},
{{3, 4}, {9, 10}},
};
fmt::print("1: {}\n", uom);
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, {4, 5}));
fmt::print("2: {}\n", uom);
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, {4, 8}));
fmt::print("3: {}\n", uom);
}
版画
1: {({3, 4}, (9, 10)), ({2, 3}, (8, 9))}
insertion: false
2: {({1, 4}, (4, 5)), ({2, 3}, (8, 9)), ({3, 4}, (9, 10))}
insertion: true
3: {({1, 4}, (4, 5)), ({2, 3}, (8, 9)), ({3, 4}, (9, 10))}
这也使得键类型在集合足够小时不使用任何动态分配。
奖金想法
您似乎是在手动将额外的密钥限制强加到标准容器中。考虑使用 MultiIndex:
#include <boost/container/flat_set.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
#include <iostream>
namespace bmi = boost::multi_index;
using Key = boost::container::flat_set<int, std::less<>,
boost::container::small_vector<int, 4>>;
template <> struct boost::hash<Key> {
size_t operator()(Key const& k) const {
return boost::hash_range(k.begin(), k.end());
}
};
struct Record {
Key key;
int a, b; // the pair
friend std::ostream& operator<<(std::ostream& os, Record const& r)
{
fmt::format_to(std::ostreambuf_iterator<char>(os), "{{ k:{} a:{} b:{} }}", r.key, r.a, r.b);
return os;
}
};
using Table = bmi::multi_index_container<
Record,
bmi::indexed_by< //
//bmi::ordered_non_unique<bmi::tag<struct byKey>,
//bmi::member<Record, Key, &Record::key>>,
bmi::hashed_non_unique<bmi::tag<struct byKeyHash>,
bmi::member<Record, Key, &Record::key>>,
bmi::ordered_unique<
bmi::tag<struct byFull>,
bmi::composite_key<Record, //
bmi::member<Record, Key, &Record::key>,
bmi::member<Record, int, &Record::a>,
bmi::member<Record, int, &Record::b> //
>>>>;
bool ensure(Table& uom, Key key, int a, int b) {
return uom.insert(Record{std::move(key), a, b}).second;
}
int main(){
Table uom{
{{2, 3}, 8, 9},
{{3, 4}, 9, 10},
};
fmt::print("1: {}\n", uom);
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, 4, 5));
fmt::print("2: {} count {{1,4}}:{}\n", uom, uom.count(Key{1, 4}));
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, 4, 8));
fmt::print("3: {} count {{1,4}}:{}\n", uom, uom.count(Key{1, 4}));
fmt::print("insertion: {}\n", ensure(uom, {1, 4}, 4, 5));
fmt::print("4: {} count {{1,4}}:{}\n", uom, uom.count(Key{1, 4}));
}
版画
1: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }]
insertion: true
2: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }, { k:[1, 4] a:4 b:5 }] count {1,4}:1
insertion: true
3: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }, { k:[1, 4] a:4 b:8 }, { k:[1, 4] a:4 b:5 }] count {1,4}:2
insertion: false
4: [{ k:[2, 3] a:8 b:9 }, { k:[3, 4] a:9 b:10 }, { k:[1, 4] a:4 b:8 }, { k:[1, 4] a:4 b:5 }] count {1,4}:2