如何使映射键具有两种不同的数据类型?
How to make a map key to be of two different data types?
我有一个std::unordered_map
容器,其中Key
可以有两种数据类型:
- 64 位无符号整数 具有(8 位无符号 int、8 位无符号 int、16 位无符号
- int、32 位无符号 int( 元组
但 value 是两种键类型相同的对象类型。
我尝试过的一件事是将密钥设为std::variant
,以便它可以容纳这两种类型。 根据某些条件检查,键被设置为以下类型之一:
void A::a() {
std::varaint<type1, type2> Id; //key
if (condition) {
Id = 64 bit unsigned value;
}
else {
Id = tuple<.....>;
}
}
unorderedmap[Id] = obj1;
// ^-- gives compile-time error
// (expecting Id specialized to either of the variant types)
此外,与此函数类似,我们在unordered_map
上执行 find(( 的多个函数。
unorderedmap.find(Id);
// ^-- Here also, compiler is throwing similar error
有没有办法修复 std::变体,或者我应该使用另一种方法?
这似乎工作得很好:
#include <iostream>
#include <unordered_map>
#include <string>
#include <variant>
typedef std::variant<int, std::string> mytype;
std::unordered_map<mytype, int> m;
int main()
{
m[5] = 20;
std::cout << m[5];
m["hey"] = 10;
std::cout << m["hey"];
mytype tmp = "hey";
std::cout << m[tmp];
}
所以答案基本上是:如果您尝试使用变体为地图编制索引,请确保地图的索引属于相同的变体类型。如果你使用get
或这个,你甚至可以让它工作,当map
是你想使用的变体的超集时 - 密切模拟动态语言。
编辑:
如果你想支持std::tuple
,你有几个选择。
选项 1
只需使用std::map
而不是std::unordered_map
。你不太可能看到logN
,而且根据经验std::map
实际上会更快(你也不会被需要一个世纪的重演谋杀,每次std::unordered_map
必须成长时都会发生这种情况(。
选项 2
继续使用std::unordered_map
,但实现哈希。这里有一个例子,其中包含以下改编的代码:
#include <iostream>
#include <string>
#include <variant>
#include <unordered_map>
// #include "custom_tuple.h"
// CUSTOM_TUPLE.h
#include <tuple>
namespace std{
namespace
{
// Code from boost
// Reciprocal of the golden ratio helps spread entropy
// and handles duplicates.
// See Mike Seymour in magic-numbers-in-boosthash-combine:
// https://stackoverflow.com/questions/4948780
template <class T>
inline void hash_combine(std::size_t& seed, T const& v)
{
seed ^= hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
// Recursive template code derived from Matthieu M.
template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
struct HashValueImpl
{
static void apply(size_t& seed, Tuple const& tuple)
{
HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
hash_combine(seed, get<Index>(tuple));
}
};
template <class Tuple>
struct HashValueImpl<Tuple,0>
{
static void apply(size_t& seed, Tuple const& tuple)
{
hash_combine(seed, get<0>(tuple));
}
};
}
template <typename ... TT>
struct hash<std::tuple<TT...>>
{
size_t
operator()(std::tuple<TT...> const& tt) const
{
size_t seed = 0;
HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
return seed;
}
};
}
// END CUSTOM_TUPLE.h
typedef std::variant<std::string, std::tuple<int, bool>> mytype;
std::unordered_map<mytype, int> m;
int main()
{
m[std::tuple{5, false}] = 20;
std::cout << m[std::tuple{5, false}];
m["hey"] = 10;
std::cout << m["hey"];
mytype tmp = "hey";
std::cout << m[tmp];
}
您可以将所有内容都放在标题内的namespace std{}
部分中,然后将该标头包含在您想要的任何位置(我省略了包含保护,因此 ofc 像往常一样添加它(。如果标准赶上并实现了元组哈希,只需删除头文件即可。
相关文章:
- 如何使映射键具有两种不同的数据类型?
- 生成一个类Name_class并将两种数据类型存储在一个向量中
- 使用 Arduino 发送两种不同类型的传感器数据
- 声明"t"中的两种或多种数据类型
- CPP中的单个参考代表两种或多个数据类型
- 类中的静态函数给出了错误:声明中的两种或多个数据类型
- typedef float _float32;的声明说明符中的两种或多种数据类型;
- 我如何使用GO语言读取可能是两种不同数据类型之一的HDF5属性
- 使用两种或两种以上数据类型的对象作为c++映射、OOP的关键字
- 具有两种不同数据类型的2d阵列
- 使用两种数据类型作为参数堆叠STL
- 错误:函数声明中的两种或多种数据类型
- C++ - 将 int 拆分为两种较小的数据类型
- 将数据从两种不同的数据结构插入 std::map <std::string, int> mymap 并通过套接字发送
- 一个向量在两种不同的情况下可以容纳不同的数据类型吗
- 创建包含两种不同数据类型或类的向量
- C++如何在一个向量中存储两种数据类型
- 函数定义中使用的两种数据类型to_string(long double _Val)
- 如何将两种类型的数据分配给一个变量
- 通过类/对象/数据?在两种形式之间