没有提升的自定义 type_index 订单
custom type_index order without boost
我有以下地图:
std::map<std::type_index, std::set<Status *>> statuses;
由于 std::type_index
,它在那里存储了 Status
的不同子集class。
但是我想控制这个地图中对象的顺序(例如,我有两个 classes Burn
和 Stun
继承自 Status
,我想要 typeid(Stun) < typeif(Burn)
这样当我遍历地图时我会在 std::set<Burn>
).
之前得到 std::set<Stun>
我想过实现一个自定义 type_index
class 但我似乎找不到任何方法来做到这一点而不需要提升,这是一个巨大的库,我希望不必包含到我的项目中。
关于如何在地图中自定义顺序有什么建议吗?
您可以将 type_index
包装到自定义类型中,并使用可生成所需顺序的比较器。
cppreference 中的示例使用 std::map
而不是 std::unordered_map
并使用自定义比较器进行了修改:
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
#include <memory>
struct A {
virtual ~A() {}
};
struct B : A {};
struct C : A {};
struct my_type_index {
std::type_index index = std::type_index(typeid(void));
my_type_index() = default;
my_type_index(std::type_index i) : index(i) {}
bool operator<(const my_type_index& other) const {
static std::map< std::type_index,int> rank{
{ std::type_index(typeid(A)) , 1},
{ std::type_index(typeid(B)), 2},
{ std::type_index(typeid(double)), 3},
{ std::type_index(typeid(int)), 4},
{ std::type_index(typeid(C)), 5}
};
return rank[index] < rank[other.index];
}
};
int main()
{
std::map<my_type_index, std::string> type_names;
type_names[std::type_index(typeid(int))] = "int";
type_names[std::type_index(typeid(double))] = "double";
type_names[std::type_index(typeid(A))] = "A";
type_names[std::type_index(typeid(B))] = "B";
type_names[std::type_index(typeid(C))] = "C";
for (const auto& e : type_names) {
std::cout << e.first.index.name() << " " << e.second << "\n";
}
}
1A A
1B B
d double
i int
1C C
François Andrieux 建议的改进:
struct my_type_index {
std::type_index index = std::type_index(typeid(void));
int rank = 0;
my_type_index() = default;
my_type_index(std::type_index i) : index(i) {
auto it = ranks.find(i);
if (it != ranks.end()) rank = it->second;
}
static const std::map<std::type_index,int> ranks;
bool operator<(const my_type_index& other) const {
return rank < other.rank;
}
};
const std::map<std::type_index,int> my_type_index::ranks = [](){
std::map<std::type_index,int> result;
std::type_index index_order[] = {
std::type_index(typeid(A)),
std::type_index(typeid(B)),
std::type_index(typeid(double)),
std::type_index(typeid(int)),
std::type_index(typeid(C))
};
for (size_t i = 0; i < std::size(index_order);++i){ result[ index_order[i]] = i+1; }
return result;
}();
排名存储在静态地图中 ranks
并且每个实例 rank
已经在构建时进行了评估(而不是在每次比较时进行评估,即比较现在更便宜)。此外,地图现在是从一个数组生成的,它更强大(您不能再错误输入 index/rank)。此外,映射是 const
,即 find
而不是 operator[]
用于查找。不在地图中的元素将被分配为 0 级。实际上以前也是如此,但在 operator[]
之前可能会向地图添加不必要的元素。
我有以下地图:
std::map<std::type_index, std::set<Status *>> statuses;
由于 std::type_index
,它在那里存储了 Status
的不同子集class。
但是我想控制这个地图中对象的顺序(例如,我有两个 classes Burn
和 Stun
继承自 Status
,我想要 typeid(Stun) < typeif(Burn)
这样当我遍历地图时我会在 std::set<Burn>
).
std::set<Stun>
我想过实现一个自定义 type_index
class 但我似乎找不到任何方法来做到这一点而不需要提升,这是一个巨大的库,我希望不必包含到我的项目中。
关于如何在地图中自定义顺序有什么建议吗?
您可以将 type_index
包装到自定义类型中,并使用可生成所需顺序的比较器。
cppreference 中的示例使用 std::map
而不是 std::unordered_map
并使用自定义比较器进行了修改:
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
#include <memory>
struct A {
virtual ~A() {}
};
struct B : A {};
struct C : A {};
struct my_type_index {
std::type_index index = std::type_index(typeid(void));
my_type_index() = default;
my_type_index(std::type_index i) : index(i) {}
bool operator<(const my_type_index& other) const {
static std::map< std::type_index,int> rank{
{ std::type_index(typeid(A)) , 1},
{ std::type_index(typeid(B)), 2},
{ std::type_index(typeid(double)), 3},
{ std::type_index(typeid(int)), 4},
{ std::type_index(typeid(C)), 5}
};
return rank[index] < rank[other.index];
}
};
int main()
{
std::map<my_type_index, std::string> type_names;
type_names[std::type_index(typeid(int))] = "int";
type_names[std::type_index(typeid(double))] = "double";
type_names[std::type_index(typeid(A))] = "A";
type_names[std::type_index(typeid(B))] = "B";
type_names[std::type_index(typeid(C))] = "C";
for (const auto& e : type_names) {
std::cout << e.first.index.name() << " " << e.second << "\n";
}
}
1A A
1B B
d double
i int
1C C
François Andrieux 建议的改进:
struct my_type_index {
std::type_index index = std::type_index(typeid(void));
int rank = 0;
my_type_index() = default;
my_type_index(std::type_index i) : index(i) {
auto it = ranks.find(i);
if (it != ranks.end()) rank = it->second;
}
static const std::map<std::type_index,int> ranks;
bool operator<(const my_type_index& other) const {
return rank < other.rank;
}
};
const std::map<std::type_index,int> my_type_index::ranks = [](){
std::map<std::type_index,int> result;
std::type_index index_order[] = {
std::type_index(typeid(A)),
std::type_index(typeid(B)),
std::type_index(typeid(double)),
std::type_index(typeid(int)),
std::type_index(typeid(C))
};
for (size_t i = 0; i < std::size(index_order);++i){ result[ index_order[i]] = i+1; }
return result;
}();
排名存储在静态地图中 ranks
并且每个实例 rank
已经在构建时进行了评估(而不是在每次比较时进行评估,即比较现在更便宜)。此外,地图现在是从一个数组生成的,它更强大(您不能再错误输入 index/rank)。此外,映射是 const
,即 find
而不是 operator[]
用于查找。不在地图中的元素将被分配为 0 级。实际上以前也是如此,但在 operator[]
之前可能会向地图添加不必要的元素。