我需要制作一个lambda,该lambda返回一个元组,用于对对象向量进行排序。元组从对象中收集属性的集合。一些属性是对不应复制的大对象的引用(下面的代码中的f()
),其他属性是较小的r值(下面的代码中的g()
)。编写lambda的最简单或最惯用的方法是什么?
#include <vector>
#include <tuple>
#include <algorithm>
struct A {
std::vector<int> const &f() const;
int g() const;
};
void example() {
auto sort_key = [](A const &a) {
//return std::tuple{a.f(), a.g()}; // copies the vector from f()
//return std::tie(a.f(), a.g()); // can't bind the int from g()
//return std::forward_as_tuple(a.f(), a.g()); // returns a reference to the int from g(), which expires when this function returns
return std::tuple<std::vector<int> const &, int>{a.f(), a.g()}; // works, but requires specifying the types
};
std::vector<A> v;
std::sort(v.begin(), v.end(), [&](A const &a, A const &b) {
return sort_key(a) < sort_key(b);
});
}
我很尴尬地说forward_as_tuple是我的第一次尝试,经过长时间的调试会话后,我意识到它正在为第二个属性返回int &&,该值超出范围。用这种方式写是肌肉记忆,因为据我的理解,forward_as_tuple(...) < forward_as_tuple(...)
非常好:由于所有内容都在一行代码中,因此我们可以延长所有引用的生命周期。
在构造元组时明确指定类型-第一属性的引用,第二属性的值,这就是我现在正在做的事情,但是我更喜欢清洁的东西。 (好吧,事实是这还不错,但是我问是因为我很好奇是否有更好的东西。)
我可能可以建立一个辅助函数,将其称为forward_references_but_copy_rvalues,但是标准库中已经可以执行此操作?