MSVC升级至19.28+后自定义迭代器跨容器排序功能失效问题求助
问题原因
MSVC 16.8版本开始将std::sort的底层实现替换为性能更高的PdqSort算法,新实现对迭代器的契约符合性要求更严格,你的自定义代理迭代器存在多处不符合随机访问迭代器要求的问题,同时MSVC的新实现会用到之前旧版sort未用到的迭代器操作:
- 缺少随机访问迭代器强制要求的
+=/-=运算符实现 - const版本的解引用运算符
operator*返回了值类型而非代理引用类型,导致部分路径下操作的是临时对象而非实际数组元素 - 部分场景下自定义swap的ADL查找优先级不足
解决方案
按如下步骤修改代码即可兼容MSVC 19.28+版本,同时保留对GCC/Clang的兼容性:
- 为
ValueIterator补充+=/-=运算符实现 - 修改const版本
operator*的返回值为const代理引用类型 - 将自定义swap函数声明为
ValueReference的友元,确保ADL能正确查找 - 补充
ValueReference到Value的显式转换运算符,避免隐式转换异常
完整修改后代码
#include <iterator> #include <algorithm> #include <iostream> namespace SortHelper { template <typename OrderT, typename DataT> struct ValueReference; template <typename OrderT, typename DataT> struct Value { OrderT Order; DataT Data; Value(OrderT order, DataT data) : Order(order), Data(data) { } Value(const ValueReference<OrderT, DataT>& rhs); bool operator <(const Value<OrderT, DataT>& rhs) const { return Order < rhs.Order; } }; template <typename OrderT, typename DataT> struct ValueReference { OrderT* Order; DataT* Data; ValueReference(OrderT* orderIterator, DataT* dataIterator) : Order(orderIterator), Data(dataIterator) { } ValueReference& operator =(const ValueReference& rhs) { *Order = *rhs.Order; *Data = *rhs.Data; return *this; } ValueReference& operator =(const Value<OrderT, DataT>& rhs) { *Order = rhs.Order; *Data = rhs.Data; return *this; } bool operator <(const ValueReference& rhs) const { return *Order < *rhs.Order; } // 显式转换到Value,避免隐式转换问题 operator Value<OrderT, DataT>() const { return Value<OrderT, DataT>(*Order, *Data); } // 将swap声明为友元,保证ADL查找优先级 friend void swap(ValueReference lhs, ValueReference rhs) { std::swap(*lhs.Order, *rhs.Order); std::swap(*lhs.Data, *rhs.Data); } }; template <typename OrderT, typename DataT> struct ValueIterator { typedef Value<OrderT, DataT> value_type; typedef Value<OrderT, DataT>* pointer; typedef ValueReference<OrderT, DataT> reference; typedef const ValueReference<OrderT, DataT> const_reference; typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; OrderT* OrderIterator; DataT* DataIterator; ValueIterator(OrderT* orderIterator, DataT* dataIterator) : OrderIterator(orderIterator), DataIterator(dataIterator) { } std::ptrdiff_t operator -(const ValueIterator& rhs) const { return OrderIterator - rhs.OrderIterator; } ValueIterator operator +(std::ptrdiff_t off) const { return ValueIterator(OrderIterator + off, DataIterator + off); } ValueIterator operator -(std::ptrdiff_t off) const { return ValueIterator(OrderIterator - off, DataIterator - off); } // 补充随机访问迭代器要求的+=/-=运算符 ValueIterator& operator +=(std::ptrdiff_t off) { OrderIterator += off; DataIterator += off; return *this; } ValueIterator& operator -=(std::ptrdiff_t off) { OrderIterator -= off; DataIterator -= off; return *this; } ValueIterator& operator ++() { ++OrderIterator; ++DataIterator; return *this; } ValueIterator& operator --() { --OrderIterator; --DataIterator; return *this; } ValueIterator operator ++(int) { return ValueIterator(OrderIterator++, DataIterator++); } ValueIterator operator --(int) { return ValueIterator(OrderIterator--, DataIterator--); } // 修改const版本解引用返回const代理引用,而非临时值对象 const ValueReference<OrderT, DataT> operator *() const { return ValueReference<OrderT, DataT>(OrderIterator, DataIterator); } ValueReference<OrderT, DataT> operator [](difference_type n) const { return ValueReference<OrderT, DataT>(OrderIterator + n, DataIterator + n); } ValueReference<OrderT, DataT> operator *() { return ValueReference<OrderT, DataT>(OrderIterator, DataIterator); } bool operator <(const ValueIterator& rhs) const { return OrderIterator < rhs.OrderIterator; } bool operator ==(const ValueIterator& rhs) const { return OrderIterator == rhs.OrderIterator; } bool operator !=(const ValueIterator& rhs) const { return OrderIterator != rhs.OrderIterator; } }; template <typename OrderT, typename DataT> Value<OrderT, DataT>::Value(const ValueReference<OrderT, DataT>& rhs) : Order(*rhs.Order), Data(*rhs.Data) { } template <typename OrderT, typename DataT> bool operator <(const Value<OrderT, DataT>& lhs, const ValueReference<OrderT, DataT>& rhs) { return lhs.Order < *rhs.Order; } template <typename OrderT, typename DataT> bool operator <(const ValueReference<OrderT, DataT>& lhs, const Value<OrderT, DataT>& rhs) { return *lhs.Order < rhs.Order; } } int main() { int Age[] = { 45, 14, 5, 24 }; const char* Names[] = { "Karl", "Paul", "Martin", "Jennie" }; std::sort(SortHelper::ValueIterator<int, const char*>(Age, Names), SortHelper::ValueIterator<int, const char*>(Age + 4, Names + 4)); for (int i = 0; i < 4; ++i) std::cout << Age[i] << ": " << Names[i] << "\n"; }
修改后的代码在MSVC 19.28+、GCC、Clang下均可正常输出预期结果:
5: Martin 14: Paul 24: Jennie 45: Karl
内容的提问来源于stack exchange,提问作者stfx
相关产品推荐
相关产品推荐

