为什么我可以使用模板函数作为 std::sort 的参数,但不能使用模板 lambda(使用成员函数 ptr 作为模板参数)[重复]

问题描述 投票:0回答:1

抱歉标题太长,正如我所说,这是有效的:

struct S { int a{}, b{}; };
std::ostream &operator<<(std::ostream &o, const S &s) { return o << '{' << s.a << ',' << s.b << '}'; }

template <auto ptr>
bool f(const S &a, const S &b)
{
    return a.*ptr < b.*ptr;
}

int main()
{
    std::vector<S> v{{1,9},{2,8},{3,7},{4,6},{6,4},{7,3},{8,2},{9,1}};

    std::sort(v.begin(), v.end(), f<&S::b>);
    //          Sort by S::b -----> ^^^^^

    for (const auto &s : v)
        std::cout << s << ' ';
    // output: {9,1} {8,2} {7,3} {6,4} {4,6} {3,7} {2,8} {1,9} 

    return 0;
}

但这不是:

    …

    auto l = []<auto ptr>(const S &a, const S &b)
    {
        return a.*ptr < b.*ptr;
    };

    std::sort(v.begin(), v.end(), l<&S::b>);
    //         Sort by S::b? -----> ^^^^^
    …

这是错误:

error: no match for 'operator<' (operand types are 'main()::<lambda(const S&, const S&)>' and 'int S::*')
std::sort(v.begin(), v.end(), l<&S::b>);
                              ~^~~~~~

看起来 lambda 的模板符号作为

std::sort
的参数被视为
l
小于 (
<
)
&S::b>
的比较,这不是我的意图。

我应该如何将模板 lambda 传递给

std::sort
函数?

c++ templates lambda
1个回答
1
投票

你可以这样做:

std::ranges::sort(v, {}, &S::b)


您的版本不起作用,因为

l
不是模板。它是一个带有模板化
operator()
的类实例。

&decltype(l)::operator()<&S::b>
可以编译,但是生成的成员指针不是
std::sort
可以使用的。

如果您使用 lambda

static
[](...) static {...}
,C++23 功能),或者将该表达式包装在
std::bind_front(..., l)
或等效项中,它将起作用。

老实说,如果您出于某种原因不想使用

std::ranges::sort()
,我会忘记模板并执行以下操作:

auto l = [](auto ptr)
{
    return [ptr](const S &a, const S &b)
    {
        return a.*ptr < b.*ptr;
    };
};

std::sort(v.begin(), v.end(), l(&S::b));
© www.soinside.com 2019 - 2024. All rights reserved.