如何在lambda中捕获变量

Pio*_*icz 6 c++ lambda

我有来自这里的代码:

std::sort(begin(v), end(v), [](auto const &t1, auto const &t2) {
        return get<0>(t1) < get<0>(t2); // or use a custom compare function
});
Run Code Online (Sandbox Code Playgroud)

我想多次排序元组,所以我编写了这段代码:

int k = 10;
while(k--){
    std::sort(begin(v), end(v), [](auto const &t1, auto const &t2) {
    return get<k>(t1) < get<k>(t2); // or use a custom compare function
    });
}
Run Code Online (Sandbox Code Playgroud)

但我得到错误error: ‘k’ is not captured.我试着这样做:

int k = 10;
while(k--){
    std::sort(begin(v), end(v), [&k](auto const &t1, auto const &t2) {
    return get<k>(t1) < get<k>(t2); // or use a custom compare function
    });
}
Run Code Online (Sandbox Code Playgroud)

但它不是正确的方法和错误error: the value of ‘k’ is not usable in a constant expression发生.

如何捕获k变量?

xsk*_*xzr 5

正如mch在评论中所说,问题在于它k不是编译时常量.

对于编译时常量,要迭代N到0,您可能需要模板和递归:

#include <algorithm>
#include <tuple>
#include <type_traits>
#include <vector>

using namespace std; // just for simplify, and not recommended in practice

template <size_t N, typename Iterator, enable_if_t<N == 0, int> = 0>
void foo(Iterator begin, Iterator end)
{
    sort(begin, end,
        [](const auto &t1, const auto &t2) {
            return get<0>(t1) < get<0>(t2); 
        }
    );
}

template <size_t N, typename Iterator, enable_if_t<N != 0, int> = 0>
void foo(Iterator begin, Iterator end)
{
    sort(begin, end,
        [](const auto &t1, const auto &t2) {
            return get<N>(t1) < get<N>(t2); 
        }
    );
    foo<N - 1>(begin, end);
}

int main()
{
    vector<tuple<int, int>> v{{0, 1}, {0, 0}, {1, 1}};
    foo<1>(v.begin(), v.end());

    // posible results:
    // {0, 0}, {0, 1}, {1, 1}
    // {0, 1}, {0, 0}, {1, 1} // impossible if use std::stable_sort instead
}
Run Code Online (Sandbox Code Playgroud)


Ark*_*lin 4

std::get只接受模板参数,该参数是一个可以在编译时计算其值的表达式。您不能使用k,因为它是一个会更改值的变量。

std::sort(begin(v), end(v), [](auto const &t1, auto const &t2) {
    const int k = 3;
    return std::get<k>(t1) < std::get<k>(t2); // or use a custom compare function
});
Run Code Online (Sandbox Code Playgroud)

正如我在评论中所写,我知道const int = 3会隐藏klambda 表达式之外的值,但这个示例表明,get当它收到编译时间常量值时,它将起作用。例如,如果您尝试设置k = 5,例如 wherev只有 4 个元组参数,编译器将给出错误,因为它知道这超出了范围。

下面的代码会报错,但是如果k设置为3就可以了

std::vector<std::tuple<int, int, int, int>> v;
std::sort(begin(v), end(v), [](auto const &t1, auto const &t2) {
            const int k = 5;
            return std::get<k>(t1) < std::get<k>(t2); // or use a custom compare function
        });
Run Code Online (Sandbox Code Playgroud)