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

未调用std::equal_to<void>却触发C3889错误?求技术解答

C3889错误分析与解决方案

开发大型C++项目时,使用Visual Studio 2022持续触发C3889错误,错误信息如下:

error C3889: call to object of class type 'std::equal_to<void>': no matching call operator found
note: could be 'unknown-type std::equal_to<void>::operator ()(_Ty1 &&,_Ty2 &&) noexcept(<expr>) const'
note: Failed to specialize function template 'unknown-type std::equal_to<void>::operator ()(_Ty1 &&,_Ty2 &&) noexcept(<expr>) const'
note: With the following template arguments:
note: '_Ty1=const _Ty &'
note: '_Ty2=const _Ty &'
note: binary '==': 'const _Ty' does not define this operator or a conversion to a type acceptable to the predefined operator
        with
        [
            _Ty=Spot
        ]

未显式调用std::equal_to<void>却出现该错误,最小复现示例(MRE)如下:

#include <iostream>
#include <vector>
template <typename T>
bool isin(T i, const std::vector<T>& vec) {
    for (const T& t : vec) {
        if (i == t) return true;
    }
    return false;
}
template <typename T>
std::vector<std::vector<T>> GetAllUniqueCombos(const std::vector<T>& arr) {
    std::vector<std::vector<T>> n;
    for (int i = 0; i < arr.size(); ++i) {
        for (int j = i + 1; j < arr.size(); ++j) {
            if (!isin({ arr[i], arr[j] }, n))n.push_back({ arr[i], arr[j] });
        }
    }
    return n;
}
struct Spot {
    int x, y;
};
void DrawTriangle(Spot s1, Spot s2, Spot s3, int color);
void DrawPolygon(const std::vector<Spot>& points, int color) {
    if (points.size() < 3) return;
    std::vector<Spot> a;
    for (int j = 1; j < points.size(); j++) {
        a.push_back(points[j]);
    }
    for (auto i : GetAllUniqueCombos(a)) {
        DrawTriangle(points[0], i[0], i[1], color);
    }
}
int main() {
    DrawPolygon({ {25, 25}, {50, 50}, {25, 50}, {50, 25} }, 0xffaa55);
}

错误原因

  1. 核心问题:std::vector的==依赖元素的相等运算符
    当isin函数的模板参数T推导为std::vector<Spot>时,代码中的i == t会调用std::vector的默认相等运算符。该运算符会逐元素比较,要求Spot类型必须支持==运算,但你的Spot结构体未重载operator==,导致编译失败。
  2. std::equal_to<void>的出现逻辑
    Visual Studio编译器在处理std::vector的相等比较时,内部会使用C++14引入的透明比较器std::equal_to<void>,所以错误信息中会提及该类型,但本质问题还是Spot缺少相等运算符。

解决方案

方式一:为Spot重载operator==

直接为Spot添加相等判断逻辑,让std::vector的默认比较可以正常工作:

struct Spot {
    int x, y;
    bool operator==(const Spot& other) const {
        return x == other.x && y == other.y;
    }
};

方式二:自定义isin函数的比较逻辑

如果不想修改Spot结构体,可以针对std::vector<Spot>特化isin函数,或者添加比较器参数实现通用逻辑:

特化版本

template <>
bool isin(std::vector<Spot> i, const std::vector<std::vector<Spot>>& vec) {
    for (const auto& t : vec) {
        if (i.size() == t.size() && 
            i[0].x == t[0].x && i[0].y == t[0].y && 
            i[1].x == t[1].x && i[1].y == t[1].y) {
            return true;
        }
    }
    return false;
}

通用比较器版本

template <typename T, typename Compare = std::equal_to<T>>
bool isin(T i, const std::vector<T>& vec, Compare comp = Compare{}) {
    for (const T& t : vec) {
        if (comp(i, t)) return true;
    }
    return false;
}

// 调用时传入自定义比较逻辑
if (!isin({ arr[i], arr[j] }, n, [](const std::vector<Spot>& a, const std::vector<Spot>& b) {
    return a.size() == b.size() && 
           a[0].x == b[0].x && a[0].y == b[0].y && 
           a[1].x == b[1].x && a[1].y == b[1].y;
}))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:35:06