【问题标题】:Got an Error when using C++20 Polymorphism Lambda Function使用 C++20 多态 Lambda 函数时出错
【发布时间】:2021-06-28 06:18:09
【问题描述】:

我正在尝试通过 C++ 中的 Lambda 编写一个高阶函数,并得到了这段代码。

void ProcessList::SortCol(std::string col, bool flag) {

    auto CmpGenerator = [&]<typename T>
        (std::function<T(const Process &itm)> func) {
        return (flag? [&](const Process &a, const Process &b) {
                            return func(a) < func(b);}
                    : [&](const Process &a, const Process &b) {
                            return func(a) > func(b);}
            );
        };

    std::function<bool(const Process &a, const Process &b)> cmp;

    if (col == "PID") {
        cmp = CmpGenerator([](const Process &itm) {
            return itm.GetPid();
        });
    }
    else if (col == "CPU") {
        cmp = CmpGenerator([](const Process &itm) {
            return itm.GetRatioCPU();
        });
    }
    else if (col == "COMMAND") {
        cmp = CmpGenerator([](const Process &itm) {
            return itm.GetCmd();
        });
    }
    std::sort(lst.begin(), lst.end(), cmp);
}

但是在编译时,g++ 报告调用不匹配

no match for call to ‘(ProcessList::SortCol(std::string, bool)::<lambda(std::function<T(const Process&)>)>) (ProcessList::SortCol(std::string, bool)::<lambda(const Process&)>)’

这里的代码有什么问题?

【问题讨论】:

  • 您不能为此使用std::ranges::sort(),并投影到指向成员(-函数)的指针吗?
  • 相当正确,但我想知道为什么这里的代码在地球上不起作用
  • 除此之外:即使它可以正确推断出 T,CmpGenerator 也会返回一个捕获到 func 的悬空引用的 lambda

标签: c++ lambda c++20 higher-order-functions


【解决方案1】:

此示例中的主要问题是 lambda 不是 std::function。见this question

CmpGenerator 将其参数推导出为 std::function&lt;T(Process const&amp;)&gt;,但 lambda 永远不会匹配,因此推导失败。

此外,CmpGenerator 的主体试图返回两个不同的 lambdas 之一——它们具有不同的类型。这些 lambda 不能相互转换,因此条件表达式将失败。但我们也无法推断出CmpGenerator 的返回类型,因为两个不同的 lambda 具有不同的类型。


我们可以从完全手动开始。 std::ranges::sort 进行投影,在这方面很有帮助:

if (col == "PID") {
    if (increasing) { // <== 'flag' is not a great name
        std::ranges::sort(lst, std::less(), &Process::GetPid);
    } else {
        std::ranges::sort(lst, std::greater(), &Process::GetPid);
    }
} else if (col == "CPU") {
    // ...
}

这给出了我们需要抽象的结构:我们不是在生成比较对象,而是在生成对sort 的调用。

即:

auto sort_by = [&](auto projection){ // <== NB: auto, not std::function
    if (increasing) {
        std::ranges::sort(lst, std::less(), projection);
    } else {
        std::ranges::sort(lst, std::greater(), projection);
    }
};

if (col == "PID") {
    sort_by(&Process::GetPid);
} else if (col == "CPU") {
    sort_by(&Process::GetRatioCPU);
} else if (col == "COMMAND") {
    sort_by(&Process::GetCmd);
}

【讨论】:

    猜你喜欢
    • 2021-06-22
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 2020-08-15
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    相关资源
    最近更新 更多