【问题标题】:lambda function doesn't matches argument listlambda 函数与参数列表不匹配
【发布时间】:2021-09-26 23:18:55
【问题描述】:

我正在使用 lambda 函数进行训练,并创建了一个使用模板类合并两个列表的小函数。我想使用 lambda 函数来比较年龄并将它们合并到一个新的列表中,该列表将按升序排列。 编译器告诉no instance of function template "merge_func" matches the argument list。 如果你能帮助我理解我的 lambda 函数出了什么问题,我该如何纠正它。

 template <class T>
list<T*> merge_func(list<T*> first_list, list<T*> second_list, bool(*func)(T x, T y))
{
    list<T> merge_list;
    auto it_first = first_list.begin();
    auto it_second = second_list.begin();
    while (it_first != first_list.end() && it_second != second_list.end())
    {
        if ((*func)(*it_first, *it_second))
        {
            merge_list.push_back((*it_first));
            it_first++;
        }
        else
        {
            merge_list.push_back((*it_second));
            it_second++;
        }
    }
    while (it_first != first_list.end())
    {
        merge_list.push_back((*it_first));
        it_first++;
    }
    while (it_second != second_list.end())
    {
        merge_list.push_back((*it_second));
        it_second++;
    }
    return merge_list;
}

class Student
{
public:
    string _name;
    double _age;
    Student(string name, double age) : _name(name), _age(age) {};
};
int main()
{
    list<Student*> std;
    std.push_back(new Student("Lior", 15.5));
    std.push_back(new Student("Yossi", 60));

    list<Student*> std2;
    std2.push_back(new Student("Arie", 23));
    std2.push_back(new Student("Eli", 80));

    list<Student*> std3;

    std3 = merge_func(std, std2, [](Student* x, Student* y)->bool {return x->_age < y->_age; });

【问题讨论】:

  • 您的列表存储 指针 而不是对象。 list&lt;T&gt; 应该是 list&lt;T*&gt;
  • 您的列表的模板类型为 Student*,但您的 lambda 需要 Student 参数。这两个不匹配
  • 您的 second 问题是您的回调将其参数作为 objects,而不是作为指针。
  • @Someprogrammerdude 谢谢我已经纠正了你所说的但仍然没有编译。 callback 是什么意思。看我的代码我编辑它
  • 请不要在给出一些有效的 cmets 或答案后更改您的代码。这样你就可以让这些答案看起来是错误的。这也使您的问题对可能有类似问题并为他们寻求解决方案的其他人无法使用。如果您想在原始代码下方显示一个固定代码附加它。

标签: c++ list pointers templates lambda


【解决方案1】:

两个问题。

  1. list的元素类型是Student*,lambda也应该取Student*

  2. 您将 lambda 传递给 merge_func,它需要一个函数指针。模板实参推导不考虑隐式转换(从 lambda 到函数指针),在第三个函数参数上推导模板形参T 失败。

你可以把merge_func改成

template <class T>
list<T> merge_func(list<T> first_list, list<T> second_list, bool(*func)(T x, T y))

并在调用merge_func时将lambda转换为函数指针。

std3 = merge_func(std, std2, static_cast<bool(*)(Student* x, Student* y)>([](Student* x, Student* y)->bool {return x->_age < y->_age; }));

或者使用sorcery operator+进行转换。

std3 = merge_func(std, std2, +[](Student* x, Student* y)->bool {return x->_age < y->_age; });

LIVE

或者防止对第三个函数参数进行扣减。

template <class T>
list<T> merge_func(list<T> first_list, list<T> second_list, std::type_identity_t<bool(*)(T x, T y)> func)

LIVE

【讨论】:

  • 谢谢!如果我理解所有问题是我使用 template 并且编译器不知道如何使用模板将 lambda 转换为函数指针? (巫师不行……)
  • @Ronyco123 为什么operator+ 不起作用?应该保证。我试过了,效果很好。 wandbox.org/permlink/nNtK4tnV3zMJx2zz
  • 我在 Visual Studio 上,operator+ 不工作。但是第一个解决方案效果很好。
  • @Ronyco123 知道了。这可能只是 MSVC 的错误。
【解决方案2】:

除了@songyuanyao 的回答,您还可以使用更通用的版本。 那么merge_func的原型应该是这样的:

template <class T, class Compare>
list<T> merge_func(list<T> first_list, list<T> second_list, Compare&& comp)

以及里面的if:

if (invoke(std::forward<Compare>(comp),*it_first, *it_second))

那么它就可以用 lambda 调用了:

std3 = merge_func(std, std2, [](Student* x, Student* y) {return x->_age < y->_age; });

Demo

SFINAE/概念相关的代码留给你写;)

【讨论】:

    猜你喜欢
    • 2016-11-20
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 2012-10-12
    • 1970-01-01
    • 2021-11-12
    相关资源
    最近更新 更多