C++ map容器降序编译报错:error: no matching function for call to object of type ‘const MyCompare‘

今天在学习C++的map容器排序时,跟着老师的课程做map容器的降序排序时编译报错,报错提示:

error: no matching function for call to object of type 'const MyCompare'

对着老师的代码看了半天,确认一个字符都没有敲错。但是视频中老师的可以正常输出,我这一摸一样的代码确报错。搞的很是恼火。。。

我的代码:

#include <iostream>
#include <string>
#include <map>
using namespace std;

//map容器排序

//排序用仿函数
class MyCompare
{
public:
    bool operator()(int v1, int v2)
    {
        return v1 > v2;
    }
};

//打印输出函数
void printMap(const map<int, string, MyCompare> &m)
{
    for (map<int, string, MyCompare>::const_iterator it = m.begin(); it != m.end(); it++)
    {
        cout << "序号:" << (*it).first << "  姓名:" << it->second << endl;
    }
    cout << endl;
};


void test01()
{
    //创建map容器对象
    map<int, string, MyCompare> m1;

    //插入数据
    m1.insert(make_pair(5, "黄忠"));
    m1.insert(make_pair(3, "张飞"));
    m1.insert(make_pa
报错:guo@guo-Dell-G15-5520:~/g2o仿真/src/build$ make Consolidate compiler generated dependencies of target g2o_demo [ 50%] Building CXX object CMakeFiles/g2o_demo.dir/optimize.cc.o /home/guo/g2o仿真/src/optimize.cc: In function ‘std::vector<g2o::SE3Quat> addNoise(const std::vector<g2o::SE3Quat>&, double, double, bool)’: /home/guo/g2o仿真/src/optimize.cc:90:61: error: no match for ‘operator*’ (operand types are ‘g2o::SE3Quat’ and ‘const Quaternion’ {aka ‘const Eigen::Quaternion<double>’}) 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~ | | | | g2o::SE3Quat const Quaternion {aka const Eigen::Quaternion<double>} In file included from /home/guo/g2o仿真/src/optimize.cc:11: /opt/ros/noetic/include/g2o/types/slam3d/se3quat.h:99:22: note: candidate: ‘g2o::SE3Quat g2o::SE3Quat::operatonst Eigen::MatrixBase<U>&)’ 325 | operator*(const TranspositionsBase<TranspositionsDerived> &transpositions, | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/Core/Transpositions.h:325:1: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::TranspositionsBase<TranspositionsDerived>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/local/include/eigen3/Eigen/Householder:24, from /usr/local/include/eigen3/Eigen/QR:15, from /usr/local/include/eigen3/Eigen/SVD:11, from /usr/local/include/eigen3/Eigen/Geometry:13, from /home/guo/g2o仿真/src/optimize.cc:5: /usr/local/include/eigen3/Eigen/src/Householder/HouseholderSequence.h:513:99: note: candidate: ‘template<class OtherDerived, class VectorsType, class CoeffsType, int Side> typename Eigen::internal::matrix_type_times_scalar_type<typename VectorsType::Scalar, OtherDerived>::Type Eigen::operator*(const Eigen::MatrixBase<Derived>&, const Eigen::HouseholderSequence<VectorsType, CoeffsType, Side>&)’ 513 | typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::Type operator*(const MatrixBase<OtherDerived>& other, const HouseholderSequence<VectorsType,CoeffsType,Side>& h) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/Householder/HouseholderSequence.h:513:99: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::MatrixBase<Derived>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/local/include/eigen3/Eigen/Geometry:46, from /home/guo/g2o仿真/src/optimize.cc:5: /usr/local/include/eigen3/Eigen/src/Geometry/Scaling.h:135:1: note: candidate: ‘template<class Derived, class Scalar> Eigen::CwiseBinaryOp<Eigen::internal::scalar_product_op<typename Eigen::internal::traits<T>::Scalar, Scalar>, const Derived, const typename Eigen::internal::plain_constant_type<Expr, Scalar>::type> Eigen::operator*(const Eigen::MatrixBase<Derived>&, const Eigen::UniformScaling<Scalar>&)’ 135 | operator*(const MatrixBase<Derived>& matrix, const UniformScaling<Scalar>& s) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/Geometry/Scaling.h:135:1: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::MatrixBase<Derived>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/local/include/eigen3/Eigen/SparseCore:62, from /usr/local/include/eigen3/Eigen/Sparse:26, from /opt/ros/noetic/include/g2o/solvers/eigen/linear_solver_eigen.h:30, from /home/guo/g2o仿真/src/optimize.cc:10: /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:147:1: note: candidate: ‘template<class SparseDerived, class PermDerived> const Eigen::Product<MatrixDerived, PermutationDerived, 2> Eigen::operator*(const Eigen::SparseMatrixBase<OtherDerived>&, const Eigen::PermutationBase<PermutationDerived>&)’ 147 | operator*(const SparseMatrixBase<SparseDerived>& matrix, const PermutationBase<PermDerived>& perm) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:147:1: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::SparseMatrixBase<OtherDerived>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/local/include/eigen3/Eigen/SparseCore:62, from /usr/local/include/eigen3/Eigen/Sparse:26, from /opt/ros/noetic/include/g2o/solvers/eigen/linear_solver_eigen.h:30, from /home/guo/g2o仿真/src/optimize.cc:10: /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:154:1: note: candidate: ‘template<class SparseDerived, class PermDerived> const Eigen::Product<PermDerived, SparseDerived, 2> Eigen::operator*(const Eigen::PermutationBase<PermutationDerived>&, const Eigen::SparseMatrixBase<OtherDerived>&)’ 154 | operator*( const PermutationBase<PermDerived>& perm, const SparseMatrixBase<SparseDerived>& matrix) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:154:1: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::PermutationBase<PermutationDerived>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/local/include/eigen3/Eigen/SparseCore:62, from /usr/local/include/eigen3/Eigen/Sparse:26, from /opt/ros/noetic/include/g2o/solvers/eigen/linear_solver_eigen.h:30, from /home/guo/g2o仿真/src/optimize.cc:10: /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:162:1: note: candidate: ‘template<class SparseDerived, class PermutationType> const Eigen::Product<SparseDerived, Eigen::Inverse<Rhs>, 2> Eigen::operator*(const Eigen::SparseMatrixBase<OtherDerived>&, const Eigen::InverseImpl<PermutationType, Eigen::PermutationStorage>&)’ 162 | operator*(const SparseMatrixBase<SparseDerived>& matrix, const InverseImpl<PermutationType, PermutationStorage>& tperm) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:162:1: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::SparseMatrixBase<OtherDerived>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/local/include/eigen3/Eigen/SparseCore:62, from /usr/local/include/eigen3/Eigen/Sparse:26, from /opt/ros/noetic/include/g2o/solvers/eigen/linear_solver_eigen.h:30, from /home/guo/g2o仿真/src/optimize.cc:10: /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:171:1: note: candidate: ‘template<class SparseDerived, class PermutationType> const Eigen::Product<Eigen::Inverse<Rhs>, SparseDerived, 2> Eigen::operator*(const Eigen::InverseImpl<PermutationType, Eigen::PermutationStorage>&, const Eigen::SparseMatrixBase<OtherDerived>&)’ 171 | operator*(const InverseImpl<PermutationType,PermutationStorage>& tperm, const SparseMatrixBase<SparseDerived>& matrix) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/SparseCore/SparsePermutation.h:171:1: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::InverseImpl<PermutationType, Eigen::PermutationStorage>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/local/include/eigen3/Eigen/Geometry:40, from /home/guo/g2o仿真/src/optimize.cc:5: /usr/local/include/eigen3/Eigen/src/Geometry/RotationBase.h:80:66: note: candidate: ‘Eigen::Transform<double, 3, 2> Eigen::operator*(const Eigen::DiagonalMatrix<double, 3>&, const Eigen::Quaternion<double>&)’ 80 | EIGEN_DEVICE_FUNC friend inline Transform<Scalar,Dim,Affine> operator*(const DiagonalMatrix<Scalar,Dim>& l, const Derived& r) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/Geometry/RotationBase.h:80:110: note: no known conversion for argument 1 from ‘g2o::SE3Quat’ toconst Eigen::DiagonalMatrix<double, 3>&’ 80 | EIGEN_DEVICE_FUNC friend inline Transform<Scalar,Dim,Affine> operator*(const DiagonalMatrix<Scalar,Dim>& l, const Derived& r) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ /usr/local/include/eigen3/Eigen/src/Geometry/RotationBase.h:76:49: note: candidate: ‘template<class OtherDerived> Eigen::RotationBase<Eigen::Quaternion<double>, 3>::RotationMatrixType Eigen::operator*(const Eigen::EigenBase<Derived>&, const Eigen::Quaternion<double>&)’ 76 | EIGEN_DEVICE_FUNC inline RotationMatrixType operator*(const EigenBase<OtherDerived>& l, const Derived& r) | ^~~~~~~~ /usr/local/include/eigen3/Eigen/src/Geometry/RotationBase.h:76:49: note: template argument deduction/substitution failed: /home/guo/g2o仿真/src/optimize.cc:90:81: note: ‘g2o::SE3Quat’ is not derived from ‘const Eigen::EigenBase<Derived>’ 90 | noisy[i].setRotation(g2o::SE3Quat::exp(rotNoiseVec) * noisy[i].rotation()); | ^ In file included from /usr/include/x86_64-linux-gnu/c++/9/bits/c++allocator.h:33, from /usr/include/c++/9/bits/allocator.h:46, from /usr/include/c++/9/string:41, from /usr/include/c++/9/bits/locale_classes.h:40, from /usr/include/c++/9/bits/ios_base.h:41, from /usr/include/c++/9/ios:42, from /usr/include/c++/9/ostream:38, from /usr/include/c++/9/iostream:39, from /home/guo/g2o仿真/src/optimize.cc:1: /usr/include/c++/9/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = g2o::SE3Quat; _Args = {Eigen::AngleAxis<double>&, Eigen::Matrix<double, 3, 1, 0, 3, 1>&}; _Tp = g2o::SE3Quat]’: /usr/include/c++/9/bits/alloc_traits.h:483:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = g2o::SE3Quat; _Args = {Eigen::AngleAxis<double>&, Eigen::Matrix<double, 3, 1, 0, 3, 1>&}; _Tp = g2o::SE3Quat; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<g2o::SE3Quat>]’ /usr/include/c++/9/bits/vector.tcc:115:30: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {Eigen::AngleAxis<double>&, Eigen::Matrix<double, 3, 1, 0, 3, 1>&}; _Tp = g2o::SE3Quat; _Alloc = std::allocator<g2o::SE3Quat>]’ /home/guo/g2o仿真/src/optimize.cc:66:54: required from here /usr/include/c++/9/ext/new_allocator.h:146:4: error: no matching function for call to ‘g2o::SE3Quat::SE3Quat(Eigen::AngleAxis<double>&, Eigen::Matrix<double, 3, 1>&)’ 146 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最新发布
08-03
<think>问题:在C++代码中遇到了编译错误:`In template: no matching function for call to 'qHash'`。这个错误通常发生在使用`QSet`或`QHash`等容器时,容器中的自定义类型没有提供`qHash`函数。 ### 原因分析 Qt的`QSet`和`QHash`容器需要为键类型(Key)计算哈希值。对于内置类型和Qt提供的类型(如`QString`),Qt已经提供了`qHash`函数。但是,如果使用自定义类型作为键,则必须提供自定义的`qHash`函数,并重载`operator==`,因为哈希表需要比较键是否相等。 ### 解决方法 为自定义类型实现`qHash`函数和`operator==`。具体步骤如下: 1. **重载`operator==`**:确保自定义类型可以比较相等。 2. **实现`qHash`函数**:计算自定义类型的哈希值,并返回`uint`类型的结果。 ### 代码示例 假设我们有一个自定义类型`TileId`(如之前瓦片地图示例中的结构体),那么需要如下实现: ```cpp struct TileId { int x, y, z; }; // 重载operator== inline bool operator==(const TileId &t1, const TileId &t2) { return t1.x == t2.x && t1.y == t2.y && t1.z == t2.z; } // 实现qHash函数 inline uint qHash(const TileId &key, uint seed = 0) { // 使用Qt提供的哈希函数组合多个字段 uint hash = qHash(key.x, seed); hash = hash * 31 + qHash(key.y, seed); hash = hash * 31 + qHash(key.z, seed); return hash; } ``` ### 注意事项 - **哈希函数质量**:应确保哈希函数有良好的分布性,避免大量冲突。 - **`seed`参数**:`qHash`函数的第二个参数是种子,用于进一步随机化哈希值,应将其用于计算中。 - **一致性**:如果`a == b`,那么必须保证`qHash(a) == qHash(b)`。 ### 完整修正代码 在之前的瓦片地图示例中,`TileId`结构体被用于`QSet`,因此需要添加上述函数。修正后的代码片段如下: ```cpp // 在TileMap类定义之前添加以下代码 struct TileId { int x, y, z; }; inline bool operator==(const TileId &t1, const TileId &t2) { return t1.x == t2.x && t1.y == t2.y && t1.z == t2.z; } inline uint qHash(const TileId &key, uint seed) { return qHash(key.x, seed) ^ qHash(key.y, seed) ^ qHash(key.z, seed); } // 或者更复杂的组合方式(推荐): inline uint qHash(const TileId &key, uint seed) { uint hash = qHash(key.x, seed); hash = hash * 31 + qHash(key.y, seed); hash = hash * 31 + qHash(key.z, seed); return hash; } ``` ### 为什么需要`qHash`函数? `QSet`和`QHash`内部使用哈希表来存储元素,因此需要为每个键计算一个哈希值。如果没有为自定义类型提供`qHash`函数,编译器无法找到合适的哈希函数,从而报错。 ### 相关问题 §§相关问题§§: 1. 在Qt中,`QSet`和`QHash`有什么区别? 2. 如何为自定义类型实现哈希函数? 3. 为什么在哈希表中需要同时提供`qHash`和`operator==`? 4. 如何避免哈希冲突?</think>### 问题分析:`no matching function for call to 'qHash'`错误 这个错误发生在使用`QSet`或`QHash`时,当容器中的自定义类型没有提供相应的`qHash`函数。在之前的代码中,我们使用了: ```cpp QSet<TileId> activeTiles; ``` 其中`TileId`是自定义结构体,但未为其实现`qHash`函数。 ### 解决方法:为自定义类型实现`qHash` 需要为`TileId`结构体实现: 1. `operator==`(用于比较相等性) 2. `qHash`函数(用于计算哈希值) #### 修正后的代码实现: ```cpp // 在TileMap类定义前添加以下代码 struct TileId { int x, y, z; // 必须重载==运算符 friend bool operator==(const TileId &a, const TileId &b) { return a.x == b.x && a.y == b.y && a.z == b.z; } }; // 为TileId实现qHash函数 inline uint qHash(const TileId &key, uint seed = 0) { // 使用Qt的哈希组合函数 uint hash = qHash(key.x, seed); hash = hash * 31 + qHash(key.y, seed); hash = hash * 31 + qHash(key.z, seed); return hash; } // 或者使用更简洁的位运算方式 // inline uint qHash(const TileId &key, uint seed) { // return qHash(key.x, seed) ^ qHash(key.y, seed) ^ qHash(key.z, seed); // } ``` ### 关键点解释 1. **为什么需要`qHash`函数**: - `QSet`和`QHash`内部使用哈希表存储数据 - 哈希表需要计算每个元素的哈希值来确定存储位置 - 对于自定义类型,Qt无法自动生成合适的哈希函数 2. **为什么需要`operator==`**: - 哈希表需要解决哈希冲突 - 当两个元素的哈希值相同时,需要比较它们是否真正相等 - 没有`operator==`,编译器无法比较自定义类型 3. **哈希函数实现要点**: - 应确保相等的对象产生相同的哈希值 - 不相等的对象应尽可能产生不同的哈希值 - 使用质数乘法(如31)可以改善哈希分布 - 可以使用`qHash`组合基本类型的哈希值 ### 完整修正代码片段 ```cpp // 前置声明qHash函数 struct TileId; inline uint qHash(const TileId &key, uint seed = 0); struct TileId { int x, y, z; friend bool operator==(const TileId &a, const TileId &b) { return a.x == b.x && a.y == b.y && a.z == b.z; } }; inline uint qHash(const TileId &key, uint seed) { uint hash = qHash(key.x, seed); hash = hash * 31 + qHash(key.y, seed); hash = hash * 31 + qHash(key.z, seed); return hash; } class TileMap : public QGraphicsScene { // 其余代码保持不变 QSet<TileId> activeTiles; // 现在可以正确编译 }; ``` ### 最佳实践建议 1. **将哈希函数放在同一命名空间**: ```cpp namespace TileSystem { struct TileId { ... }; uint qHash(const TileId &key, uint seed = 0); } ``` 2. **使用`Q_DECLARE_TYPEINFO`注册类型**: ```cpp Q_DECLARE_TYPEINFO(TileSystem::TileId, Q_MOVABLE_TYPE); ``` 3. **C++11统一初始化简化**: ```cpp struct TileId { int x, y, z; bool operator==(const TileId &o) const { return std::tie(x, y, z) == std::tie(o.x, o.y, o.z); } }; ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值