c++ - `std::set_intersection` 的 lambda 比较器

标签 c++ lambda comparator intersection

以下代码抛出编译错误

class A
{
public:
    A(int i):a(i){}
    int a;
};


int main()
{
  std::vector<A> As;
  As.push_back(A(1));
  As.push_back(A(2));
  As.push_back(A(3));
  As.push_back(A(4));
  As.push_back(A(5));

  std::vector<int> Is = {2,4};
  std::vector<int> Bs = {1,2,3,4,5};

  std::vector<A> intersection;

  std::set_intersection
  (
    As.begin(), As.end(),
    Is.begin(), Is.end(),
    std::back_inserter(intersection),
    [](int const& lhs, A const& rhs)
    {
        return lhs < rhs.a;
    }
  );
}

error: no matching function for call to object of type '(lambda at c.cpp:33:4)' if (__comp(*__first1, *__first2))

我未能为此 std::set_intersection 的比较器实现 lambda 函数。我还尝试过重载 operator> , operator<operator==上课A但它仍然失败。你能帮我一下吗?

最佳答案

这里的问题是,比较函数被双向调用,一次使用 (A,int),一次使用 (int,A)。我没有检查实现,也许预期这两种类型是相同的。

作为解决方案,您只需提供两个签名即可:

class A
{
    public:
        A(int i):a(i){}
        int a;
};

// Helper to get Lambda with multiple signatures in place 
// template deduction guide is a C++17 feature! 
template<class... Ts> struct funcs : Ts... { using Ts::operator()...; };
template<class... Ts> funcs(Ts...) -> funcs<Ts...>;

// if c++17 is not available, you have to write a functor/function
// with both signatures 

int main()
{
    std::vector<A> As;
    As.push_back(A(1)); 
    As.push_back(A(2));
    As.push_back(A(3));
    As.push_back(A(4));
    As.push_back(A(5));

    std::vector<int> Is = {2,4};
    std::vector<int> Bs = {1,2,3,4,5};

    std::vector<A> intersection;

    std::set_intersection
        (
            As.begin(), As.end(),
            Is.begin(), Is.end(),
            std::back_inserter(intersection),
            funcs{
                [](A const& lhs, int const& rhs)
                {
                    return lhs.a < rhs;
                },
                [](int const& lhs, A const& rhs)
                {
                    return lhs < rhs.a;
                }
            }
        );
}

我在 Fedora 上的 g++ (GCC) 8.1.1 20180712 (Red Hat 8.1.1-5) 下运行。如果我只提供一个签名,与首先使用 int 或 A 无关,则会收到错误:

1)

no match for call to '(main()::<lambda(const A&, const int&)>) (int&, A&)'

2)

no match for call to '(main()::<lambda(const int&, const A&)>) (A&, int&)'

因此需要提供一个在这里接受两个签名的 comp 函数。

关于c++ - `std::set_intersection` 的 lambda 比较器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52301777/

相关文章:

c++ - delete[] 是否适用于通用数组?如果是这样,为什么在其上使用 std::vector::erase 会导致释放内存时出错

单个文件中的c++循环引用

c++ - 如何参数化用作另一个 lambda 参数的 lambda

使用比较器和内部类进行 Java 排序

C++ priority_queue使用带有lambda比较器错误的 map

c++ - 如何在 C++ 中创建 map<string, class::method> 并能够搜索函数并调用它?

c++ - 如何在 MFC C++ 中开始使用线程编程?

node.js - AWS Lambda 中是否有类似 Request Scoped with Node 的东西?

c# - 预编译的 lambda 表达式以创建具有带参数的构造函数的类

c++ - 如何对同一个优先级队列使用不同的比较器?