C++11/C++14中按指定类型模式重排实例vector的实现问询
当然可以实现!不用修改现有类,C++11/14就能搞定
完全不需要改动你现有的类,咱们利用C++11/14的标准特性就能按指定类型顺序重新排列vector容器。核心思路是给每个目标类型分配一个优先级值,然后基于这个值实现自定义排序规则——优先级越高(数值越小)的类型,在容器里越靠前。
下面分两种常见场景给你具体实现方案:
场景1:编译期固定类型顺序(高效、类型安全)
如果你的类型顺序是固定的,不需要运行时调整,推荐用模板特化来定义优先级,编译期就能确定排序规则,效率更高。
步骤1:定义类型优先级模板
先写一个通用的模板结构体,然后对每个需要指定顺序的类型进行特化,给它们分配不同的优先级数值:
#include <vector> #include <algorithm> #include <climits> #include <memory> // 假设你的基类和子类是这样的(完全不用修改它们) class Base { public: virtual ~Base() = default; // 必须是多态类型,才能识别子类实际类型 }; class ClassA : public Base {}; class ClassB : public Base {}; class ClassC : public Base {}; // 通用模板:未指定的类型默认优先级最高(放最后) template<typename T> struct TypePriority { static constexpr int value = INT_MAX; }; // 特化需要排序的类型,数值越小越靠前 template<> struct TypePriority<ClassA> { static constexpr int value = 1; }; template<> struct TypePriority<ClassB> { static constexpr int value = 2; }; template<> struct TypePriority<ClassC> { static constexpr int value = 3; };
步骤2:编写优先级获取函数和排序逻辑
通过dynamic_cast判断元素的实际类型,然后返回对应的优先级,再用这个优先级做排序:
// 获取元素的优先级 int get_type_priority(Base* ptr) { if (dynamic_cast<ClassA*>(ptr)) { return TypePriority<ClassA>::value; } else if (dynamic_cast<ClassB*>(ptr)) { return TypePriority<ClassB>::value; } else if (dynamic_cast<ClassC*>(ptr)) { return TypePriority<ClassC>::value; } // 其他未指定类型默认放最后 return TypePriority<Base>::value; }
步骤3:使用示例
直接调用std::sort,用lambda传入自定义排序逻辑即可:
int main() { // 用智能指针更安全,避免内存泄漏 std::vector<std::unique_ptr<Base>> vec = { std::make_unique<ClassC>(), std::make_unique<ClassA>(), std::make_unique<ClassB>(), std::make_unique<ClassA>() }; // 排序:优先级小的类型排在前面 std::sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) { return get_type_priority(a.get()) < get_type_priority(b.get()); }); // 排序后顺序:ClassA → ClassA → ClassB → ClassC return 0; }
场景2:运行时可调整类型顺序(灵活)
如果你的类型顺序需要在运行时动态修改,比如从配置文件读取排序规则,那么可以用std::type_index和哈希表来存储优先级:
#include <typeindex> #include <unordered_map> // 运行时可修改的优先级映射表 std::unordered_map<std::type_index, int> type_priority_map = { {typeid(ClassA), 1}, {typeid(ClassB), 2}, {typeid(ClassC), 3} }; // 获取优先级的函数 int get_type_priority(Base* ptr) { auto it = type_priority_map.find(typeid(*ptr)); if (it != type_priority_map.end()) { return it->second; } return INT_MAX; // 未指定类型放最后 }
这种方式的好处是,你可以在程序运行时随时修改type_priority_map的内容,重新排序就能得到新的顺序,非常灵活。
关键注意事项
- 基类必须是多态类型:也就是基类至少要有一个虚函数(比如虚析构),这样
dynamic_cast和typeid才能正确识别元素的实际子类类型。 - 值类型容器的限制:如果你的vector存的是值类型(不是指针/智能指针),容器里只能是同一类型,这种场景下排序类型顺序没有意义,所以默认你是处理多态指针的场景。
- C++11兼容性:上面的代码完全符合C11标准,
constexpr、std::type_index、std::unique_ptr都是C11引入的特性;如果用C14,lambda的auto参数是语法糖,C11里只需把参数写为const std::unique_ptr<Base>&即可。
内容的提问来源于stack exchange,提问作者Martin Perry
相关产品推荐
相关产品推荐

