重载std::映射不同的密钥类型
Overload std::map with different key type
所以我有以下STLstd::map
容器
#include <map>
#include <vector>
// ...
class Type
{
std::string key;
int support;
};
std::map<Type, std::vector<int> > index;
我想重载地图,这样下面的两个if子句都有效:
int main()
{
std::map<Type, std::vector<int> > index;
Type type1;
type1.key = "test";
type1.support = 10;
index[type1] = std::vector<int>();
if (index.find(type1) != index.end())
{
index[type1].push_back(0);
}
// I can not make this work
if (index.find("test") != index.end())
{
index["test"].push_back(0);
}
return 0;
}
我试过这些过载:
class Type
{
public:
std::string key;
int support;
size_t operator()() const
{
return std::hash<std::string>{}(name);
}
bool operator==(const struct Type& obj) const
{
return (key == obj.key);
}
bool operator<(const struct Type& obj) const
{
return key < obj.key;
}
bool operator<(const std::string& other_key) const
{
return key < other_key;
}
bool operator==(const std::string& other_key) const
{
return other_key == key;
}
};
namespace std
{
template<>
struct hash<Type>
{
size_t operator()(const Type& obj) const
{
return obj();
}
// Specialization here does not seem to work
size_t operator()(const std::string& name) const
{
return std::hash<std::string>{}(name);
}
};
template<>
struct less<Type>
{
bool operator() (const std::string& lname, const std::string& rname)
{
return lname < rname;
}
};
由于在我的模型中,std::string key
字段唯一定义了类型,我如何重载std::map
容器,以便对容器的项进行索引?我能在C++中做到这一点吗?
附言:我知道一些代码可能是多余的过载
您需要的是称为异构查找,并且自C++14以来由std::map
支持。为此,您可以定义自己的比较器结构,并在其中提供类型is_transparent
以启用此功能。关于如何启用异构查找的详细信息,可以在这里找到。如何使用不同类型的键搜索std::map
另外请注意,虽然std::map::find()
支持它,但std::map::operator[]
不支持,因此您必须替换您的代码:
if (index.find("test") != index.end())
{
index["test"].push_back(0);
}
类似于:
auto it = index.find("test");
if( it != index.end())
it->second.push_back(0);
无论如何,您都应该这样做,因为您将进行两次查找,而不是一次查找,这在map上是非常昂贵的操作。
因此,对于您的案例,比较器应该类似于:
struct CompareType
{
using is_transparent = std::true_type;
// standard comparison (between two instances of Type)
bool operator()(const Type& lhs, const Type& rhs) const { return lhs.key < rhs.key; }
// comparisons btw Type and std::string
bool operator()( const Type& lhs, const std::string &rhs) const { return lhs.key < rhs; }
bool operator()(const std::string &lhs, const Type& rhs) const { return lhs < rhs.key; }
};
然后你创建你的地图:
std::map<Type, std::vector<int>,CompareType> index;
并且您不再需要Type
本身的中的比较方法
另一种方法是将std::less<>
作为第三个参数提交给std::map
,但在这种情况下,您缺少比较运算符,它将std::string
作为左操作数,将Type
作为右操作数,并且由于该比较运算符不能是Type
的成员,我认为通过单独的比较器进行比较更干净(那里的代码是一致的(。
我在提供的代码中看到两个问题:
- Type类不支持小于运算,当用作std::map<>时需要小于运算密钥类型
- 字符串(char数组常量(用于两个需要Type的位置:
map::find()
和map::operator[]
的参数。编译器无法从const char*转换为Type
首先,满足类型作为std::map<>的关键类型的要求:
// Define comparison/ordering of two Type instances
bool operator<(const Type& a, const Type& b)
{
return a.key < b.key;
}
其次,定义如何使用单个参数将const char*(例如"test"(隐式转换为Type:
class Type
{
public:
// Implicitly converts const char* value to instance of Type.
Type(const char* k) : key(k), support(0) {}
//...
};
这不需要任何更新的(C++11或C++14(语言功能。
简单地尝试一下:
std::map<Type, std::vector<int>, std::less<> > index;
这需要C++14。请注意,使用不带模板参数的std::less
,这允许搜索"兼容"密钥,而不仅仅是精确的key_type
。这就是您需要通过自定义比较函数"解锁"find()
的使用。
std::map
的默认第三个模板参数是std::less<key_type>
,这是更有限的。为了与C++14之前的代码保持向后兼容性,它仍然采用这种方式,但许多新代码最好在没有模板参数的情况下使用std::less
。
- SSH通过/sbin/SSH无法读取RSA密钥文件(从控制台运行)
- 允许从 std::map 的密钥窃取资源?
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 在没有密钥的情况下读取密文的剩余噪声预算
- 如何修复无效的API密钥,IP或操作权限错误?
- 所有可能的链接生成器与64位密钥
- 如何在unordered_map中更改密钥?
- 获取当前密钥状态?
- curl_easy_perform() 失败:SSL 对等证书或 SSH 远程密钥不正常
- 将密钥发送到非前台的游戏窗口
- 重载std::映射不同的密钥类型
- C 11多态映射键静态断言失败:哈希函数必须与密钥类型的参数无关
- 具有可比的密钥类型的地图
- 如何使用std :: vector作为c 中std :: unordered_map的密钥类型
- std::unordered_map:渐近{search,insert,remove}性能取决于密钥的大小和数据类型
- std::unordered_map::查找使用与密钥类型不同的类型
- 具有自定义密钥类型的STL无序映射
- 映射v.s.unordered_map中可允许的密钥类型
- C++ STL 错误的密钥类型
- 如何为多个密钥类型专门化std映射