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

为std::map实现排序比较器时遭遇编译错误,寻求技术支持

问题:无法使用std::sort对std::map按欧氏距离排序

问题背景

尝试为std::map实现自定义比较器,通过std::sort基于欧氏距离对map元素(键为ID,值为坐标向量)排序,代码如下:

#include <iostream>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>
namespace NONBCG_DATA_ALGO
{
    template<typename T>
    T distance(std::vector<T> P1, std::vector<T> P2 , int dim)
    {
        if ((typeid(T) == typeid(int)) || (typeid(T) == typeid(double)) || (typeid(T) == typeid(float)) )
        {
            float accum = 0;
            for(int i=0; i<dim; i++)
            {
                accum += pow((P2[i]-P1[i]),2);

            }
            return sqrt(accum);
        }
        else
        {
            throw std::invalid_argument("Type should be either int,double or float");
        }


    }
    
    template<typename T>
    class distance_compare_asc_comp_id_2D
    {
        public:
        distance_compare_asc_comp_id_2D(std::vector<T> ipt):Pt(ipt){};
        bool operator()(const std::pair<int,std::vector<T>>& p1,const std::pair<int,std::vector<T>>&p2)
        {
            
            if ((typeid(T) == typeid(int)) || (typeid(T) == typeid(double)) || (typeid(T) == typeid(float)) )
            {
                
                return NONBCG_DATA_ALGO::distance<T>(Pt,p1.second,2) < NONBCG_DATA_ALGO::distance(Pt,p2.second,2);

            }
            else
            {
                throw std::invalid_argument("Type should be either int,double or float");
            }

        }
        private:
        std::vector<T> Pt;
    };

};

int main() {
    // Write C++ code here
   std::map<int,std::vector<double>> right;
   right.insert(std::pair<int,std::vector<double>>(1,{2,8,3}));
   right.insert(std::pair<int,std::vector<double>>(6,{2.5,5.4,3}));
   sort(right.begin(),right.end(),NONBCG_DATA_ALGO::distance_compare_asc_comp_id_2D<double>(std::vector<double>{0.0,0.0}));

    return 0;
}

编译错误信息

In file included from /usr/include/c++/9/algorithm:62,
                 from /tmp/wxeRdlKRUn.cpp:6:
/usr/include/c++/9/bits/stl_algo.h: In instantiation of 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<NONBCG_DATA_ALGO::distance_compare_asc_comp_id_2D<double> >]':
/usr/include/c++/9/bits/stl_algo.h:4899:18:   required from 'void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >; _Compare = NONBCG_DATA_ALGO::distance_compare_asc_comp_id_2D<double>]':
/tmp/wxeRdlKRUn.cpp:70:122:   required from here
/usr/include/c++/9/bits/stl_algo.h:1968:22: error: no match for 'operator-' (operand types are 'std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >' and 'std::_Rb_tree_iterator<std::pair<const int, std::vector<double> > >')
 1968 |     std::__lg(__last - __first) * 2,
      |               ~~~~~~~^~~~~~~~~

解决方案

错误原因

std::map的底层是红黑树结构,其迭代器属于双向迭代器,仅支持++/--操作;而std::sort要求迭代器必须是随机访问迭代器(需支持operator-、operator[]等随机访问操作),因此直接对std::map调用std::sort会触发编译错误。

解决步骤

  1. 将std::map中的元素复制到支持随机访问的容器(如std::vector)
  2. 对std::vector使用自定义比较器执行排序
  3. 若需要保留排序结果,直接操作vector即可(std::map本身始终按键有序,无法修改其内部元素顺序)

修改后的代码示例

#include <iostream>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>
#include <type_traits>

namespace NONBCG_DATA_ALGO
{
    // 优化:用const引用传递vector避免拷贝,编译期检查类型合法性
    template<typename T>
    T distance(const std::vector<T>& P1, const std::vector<T>& P2, int dim)
    {
        static_assert(std::is_arithmetic_v<T>, "Type must be arithmetic (int, double, float)");
        double accum = 0.0;
        for(int i = 0; i < dim; ++i)
        {
            double diff = P2[i] - P1[i];
            accum += diff * diff; // 替换pow提升计算效率
        }
        return static_cast<T>(sqrt(accum));
    }
    
    template<typename T>
    class distance_compare_asc_comp_id_2D
    {
    public:
        distance_compare_asc_comp_id_2D(const std::vector<T>& ipt) : Pt(ipt) {};
        bool operator()(const std::pair<int, std::vector<T>>& p1, const std::pair<int, std::vector<T>>& p2)
        {
            static_assert(std::is_arithmetic_v<T>, "Type must be arithmetic (int, double, float)");
            return NONBCG_DATA_ALGO::distance(Pt, p1.second, 2) < NONBCG_DATA_ALGO::distance(Pt, p2.second, 2);
        }
    private:
        std::vector<T> Pt;
    };

};

int main() {
    std::map<int, std::vector<double>> right;
    right.insert({1, {2, 8, 3}});
    right.insert({6, {2.5, 5.4, 3}});

    // 1. 将map元素复制到vector
    std::vector<std::pair<int, std::vector<double>>> sorted_vec(right.begin(), right.end());
    // 2. 对vector执行排序
    std::sort(sorted_vec.begin(), sorted_vec.end(), 
              NONBCG_DATA_ALGO::distance_compare_asc_comp_id_2D<double>({0.0, 0.0}));

    // 输出排序结果
    for(const auto& elem : sorted_vec)
    {
        std::cout << "ID: " << elem.first 
                  << ", 坐标: [" << elem.second[0] << ", " << elem.second[1] << "]" 
                  << ", 距离原点: " << NONBCG_DATA_ALGO::distance<double>({0.0,0.0}, elem.second, 2) << "\n";
    }

    return 0;
}

额外优化说明

  • 用static_assert替代typeid检查,在编译期拦截非法类型,避免运行时异常
  • 传递vector时使用const&减少不必要的拷贝操作
  • 用diff * diff替代pow(diff,2),提升数值计算效率

内容的提问来源于stack exchange,提问作者siva_uchiha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:05:13