如何设计模板让ThreadSafeQueue的get()适配std::queue.front()与std::priority_queue.top()
实现ThreadSafeQueue的get()方法适配不同队列类型
你的模板已限定QueueType只能是std::queue<T>或std::priority_queue<T>,要实现get()方法分别调用两者的front()和top(),可以用以下几种实用方案:
方法1:C++20 constexpr if 直接判断
如果项目支持C++20,这是最简洁的实现方式,利用编译期分支直接匹配对应队列的方法:
#include <queue> #include <type_traits> template<typename T, typename QueueType, typename = std::enable_if_t<std::is_same_v<QueueType, std::queue<T>> || std::is_same_v<QueueType, std::priority_queue<T>>>> class ThreadSafeQueue { private: QueueType q; public: T& get() { if constexpr (std::is_same_v<QueueType, std::queue<T>>) { return q.front(); } else { // 模板已限定类型,此处必然是std::priority_queue<T> return q.top(); } } };
方法2:标签分发(Tag Dispatch)
这是C++11及以上版本通用的经典适配方式,通过辅助标签区分不同队列类型:
#include <queue> #include <type_traits> template<typename T, typename QueueType, typename = std::enable_if_t<std::is_same_v<QueueType, std::queue<T>> || std::is_same_v<QueueType, std::priority_queue<T>>>> class ThreadSafeQueue { private: QueueType q; // 定义区分队列类型的标签结构体 struct QueueTag {}; struct PriorityQueueTag {}; // 针对std::queue的实现 T& get_impl(QueueTag) { return q.front(); } // 针对std::priority_queue的实现 T& get_impl(PriorityQueueTag) { return q.top(); } public: T& get() { if constexpr (std::is_same_v<QueueType, std::queue<T>>) { return get_impl(QueueTag{}); } else { return get_impl(PriorityQueueTag{}); } } };
方法3:SFINAE 重载匹配
利用SFINAE特性,为不同队列类型分别重载get()方法,适配C++11及以上版本:
#include <queue> #include <type_traits> template<typename T, typename QueueType, typename = std::enable_if_t<std::is_same_v<QueueType, std::queue<T>> || std::is_same_v<QueueType, std::priority_queue<T>>>> class ThreadSafeQueue { private: QueueType q; public: // 仅当QueueType为std::queue<T>时启用该版本 template<typename Q = QueueType> std::enable_if_t<std::is_same_v<Q, std::queue<T>>, T&> get() { return q.front(); } // 仅当QueueType为std::priority_queue<T>时启用该版本 template<typename Q = QueueType> std::enable_if_t<std::is_same_v<Q, std::priority_queue<T>>, T&> get() { return q.top(); } };
额外提示
当前模板缺少线程安全的核心同步机制,实际使用时需添加互斥锁避免多线程竞态,示例如下:
#include <queue> #include <type_traits> #include <mutex> template<typename T, typename QueueType, typename = std::enable_if_t<std::is_same_v<QueueType, std::queue<T>> || std::is_same_v<QueueType, std::priority_queue<T>>>> class ThreadSafeQueue { private: QueueType q; std::mutex mtx; // 互斥锁 public: T& get() { std::lock_guard<std::mutex> lock(mtx); // 自动加锁解锁 if constexpr (std::is_same_v<QueueType, std::queue<T>>) { return q.front(); } else { return q.top(); } } // 配套的线程安全push示例 void push(const T& val) { std::lock_guard<std::mutex> lock(mtx); q.push(val); } };
内容的提问来源于stack exchange,提问作者f1msch
相关产品推荐
相关产品推荐

