所以我有以下STL std::map容器
#include <map>
#include <vector>
// ...
class Type
{
std::string key;
int support;
};
std::map<Type, std::vector<int> > index;
Run Code Online (Sandbox Code Playgroud)
我想重载地图,所以如果下面的条款工作:
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;
}
Run Code Online (Sandbox Code Playgroud)
我试过这些重载:
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;
}
};
Run Code Online (Sandbox Code Playgroud)
因为在我的模型中,std::string key字段唯一地定义了Type如何重载std::map容器以便可以索引容器的项目?我能用C++做到吗?
PS:我知道一些代码在重载中可能是多余的
您需要的是异构查找,并且std::map自C++ 14以来一直支持.为此,您可以定义自己的比较器结构并is_transparent在其中提供类型以启用此功能.有关如何启用异构查找的详细信息,请参见此处如何使用其他类型的键搜索std :: map
还要注意,虽然std::map::find()支持它std::map::operator[]没有,所以你必须替换你的代码:
if (index.find("test") != index.end())
{
index["test"].push_back(0);
}
Run Code Online (Sandbox Code Playgroud)
类似于:
auto it = index.find("test");
if( it != index.end())
it->second.push_back(0);
Run Code Online (Sandbox Code Playgroud)
无论如何你应该这样做,因为你会做两次查找,而不是其他一次,这在地图上是非常昂贵的操作.
所以对于你的情况,比较器应该是这样的:
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; }
};
Run Code Online (Sandbox Code Playgroud)
然后你通过以下方式创建地图:
std::map<Type, std::vector<int>,CompareType> index;
Run Code Online (Sandbox Code Playgroud)
你不再需要比较方法Type了
另一种方法是提交std::less<>作为第三个参数std::map,但在这种情况下你缺少比较运算符,它std::string作为左操作数和Type右操作,并且该比较运算符不能成为Type我的成员我认为通过一个单独的比较器做它更干净(代码有一致).