如何转换std::queue<Compartment<T>>为std::queue<std::optional<T>>以计算平均值?
队列类型适配与平均值计算解决方案
问题背景
你定义了如下Compartment模板类:
#include <iostream> #include <optional> #include <queue> template<typename idType> struct Compartment { std::optional<idType> value_; Compartment() { value_ = std::nullopt; } Compartment(idType value): value_ {value} { } std::optional<idType> getValue() const { return value_; } };
并创建了类型为std::queue<Compartment<float>>的队列:
std::queue<Compartment<float>> myQueue; myQueue.emplace(1.2); myQueue.emplace(); myQueue.emplace(); myQueue.emplace(1.8);
但你编写的calcAverage函数仅支持std::queue<std::optional<float>>类型参数:
template<typename T> std::optional<T> calcAverage(std::queue<std::optional<T>>& myQueue) { return std::nullopt; } template<> std::optional<float> calcAverage<float>(std::queue<std::optional<float>>& myQueue) { float sum = 0.0; int count = 0; while( !myQueue.empty() ) { if (myQueue.front()) { sum += *myQueue.front(); count++; } myQueue.pop(); } if (count != 0) return sum / count; return std::nullopt; }
需要解决两种队列类型的适配问题,以下是最恰当的处理方案:
最优方案:修改calcAverage适配Compartment类型
直接调整函数模板,让它支持std::queue<Compartment<T>>类型,避免队列转换带来的额外开销。
1. 针对Compartment队列的重载版本
直接编写一个专门处理std::queue<Compartment<T>>的函数:
template<typename T> std::optional<T> calcAverage(std::queue<Compartment<T>>& myQueue) { T sum = 0; int count = 0; while (!myQueue.empty()) { auto opt_val = myQueue.front().getValue(); if (opt_val) { sum += *opt_val; count++; } myQueue.pop(); } return count != 0 ? std::optional<T>(sum / count) : std::nullopt; }
2. 通用模板版本(支持任意带getValue()的元素)
如果需要更通用的实现,可使用模板模板参数,兼容所有拥有返回std::optional<T>的getValue()方法的队列元素:
template<typename T, template<typename> typename ElementType> std::optional<T> calcAverage(std::queue<ElementType<T>>& myQueue) { // 静态断言确保元素符合接口要求 static_assert(std::is_same_v<decltype(std::declval<ElementType<T>>().getValue()), std::optional<T>>, "队列元素必须拥有返回std::optional<T>的getValue()方法"); T sum = 0; int count = 0; while (!myQueue.empty()) { auto opt_val = myQueue.front().getValue(); if (opt_val) { sum += *opt_val; count++; } myQueue.pop(); } return count != 0 ? std::optional<T>(sum / count) : std::nullopt; }
备选方案:转换队列类型(不推荐)
如果必须使用原有的calcAverage函数,可以手动将Compartment队列转换为std::optional队列,但此方法会产生额外的内存拷贝和时间开销,若需要保留原队列,还需先复制一份:
// 假设原队列已初始化 std::queue<Compartment<float>> myQueue; // ... // 转换队列(原队列会被清空,若需保留请先复制) std::queue<std::optional<float>> convertedQueue; while (!myQueue.empty()) { convertedQueue.push(myQueue.front().getValue()); myQueue.pop(); } // 调用原calcAverage函数 auto average = calcAverage(convertedQueue);
内容的提问来源于stack exchange,提问作者Metropol_Tilkisi
相关产品推荐
相关产品推荐

