You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSVC升级至19.28+后自定义迭代器跨容器排序功能失效问题求助

问题原因

MSVC 16.8版本开始将std::sort的底层实现替换为性能更高的PdqSort算法,新实现对迭代器的契约符合性要求更严格,你的自定义代理迭代器存在多处不符合随机访问迭代器要求的问题,同时MSVC的新实现会用到之前旧版sort未用到的迭代器操作:

  1. 缺少随机访问迭代器强制要求的+=/-=运算符实现
  2. const版本的解引用运算符operator*返回了值类型而非代理引用类型,导致部分路径下操作的是临时对象而非实际数组元素
  3. 部分场景下自定义swap的ADL查找优先级不足
解决方案

按如下步骤修改代码即可兼容MSVC 19.28+版本,同时保留对GCC/Clang的兼容性:

  1. 为ValueIterator补充+=/-=运算符实现
  2. 修改const版本operator*的返回值为const代理引用类型
  3. 将自定义swap函数声明为ValueReference的友元,确保ADL能正确查找
  4. 补充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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 04:45:03