使用 tie 从元组分配 2 个 lambda
Assigning 2 lambdas from a tuple using tie
我有一个 returns 一个 std::tuple
lambda 的函数,我想使用 std::tie()
将每个 lambda 分配给一个变量
#include<tuple>
#include <iostream>
using namespace std;
auto fn(){
auto f1 = []() {cout << "ran 1" << endl;};
auto f2 = []() {cout << "ran 2" << endl;};
return make_tuple(f1, f2);
}
int main()
{
auto res = fn();
auto f1,f2; // doesn't compile
tie(f1, f2) = res;
f1();
f2();
return 0;
}
问题是 lambda 必须来自类型“auto
”,因为它们是在编译时解析的,但我不能在不定义变量的情况下将变量声明为 auto
。那么我该怎么做才能编译这段代码呢?
C++17 引入了 structured bindings,它将为您完成这项工作。使用
const auto& [f1, f2] = fn();
将创建对返回对象的引用以延长其生命周期,并引入 f1
和 f2
作为元组成员的名称。
从 C++17 开始,您可以使用结构化绑定(参见其他答案)。
在 C++17(C++11 和 C++14)之前,您可以使用带有两个单独声明的 std::get()
auto f1 = std::get<0>(res);
auto f2 = std::get<1>(res);
并且,是的:在这两种情况下,您必须同时声明和定义变量[编辑:在 C++20 之前都是如此;自 C++20 以来不一定为真]
因为可以获得f1
和f2
的类型,所以加倍使用std::get()
using type_f1 = std::remove_reference_t<decltype((std::get<0>(res)))>;
using type_f2 = std::remove_reference_t<decltype((std::get<1>(res)))>;
或者,也许更好,使用 std::tuple_element
using type_f1 = std::tuple_element_t<0, decltype(res)>;
using type_f2 = std::tuple_element_t<1, decltype(res)>;
但这不允许在未定义的情况下声明 f1
和 f2
type_f1 f1; // compilation error (before C++20) !!!
type_f2 f2; // compilation error (before C++20) !!!
因为 lambdas 类型缺少 [编辑:在 C++20 之前] 默认构造函数。
编辑:正如 Nathan Oliver 所指出的(谢谢!),从 C++20 开始,具有空捕获列表的 lambda 已启用默认构造函数。
所以,从C++20开始,编译以下代码
#include <tuple>
#include <iostream>
auto fn ()
{ return std::make_tuple(
[]() { std::cout << "ran 1" << std::endl; },
[]() { std::cout << "ran 2" << std::endl; }); }
int main()
{
auto res = fn();
std::tuple_element_t<0u, decltype(res)> f1;
std::tuple_element_t<1u, decltype(res)> f2;
f1 = std::get<0u>(res);
f2 = std::get<1u>(res);
f1();
f2();
}
我有一个 returns 一个 std::tuple
lambda 的函数,我想使用 std::tie()
#include<tuple>
#include <iostream>
using namespace std;
auto fn(){
auto f1 = []() {cout << "ran 1" << endl;};
auto f2 = []() {cout << "ran 2" << endl;};
return make_tuple(f1, f2);
}
int main()
{
auto res = fn();
auto f1,f2; // doesn't compile
tie(f1, f2) = res;
f1();
f2();
return 0;
}
问题是 lambda 必须来自类型“auto
”,因为它们是在编译时解析的,但我不能在不定义变量的情况下将变量声明为 auto
。那么我该怎么做才能编译这段代码呢?
C++17 引入了 structured bindings,它将为您完成这项工作。使用
const auto& [f1, f2] = fn();
将创建对返回对象的引用以延长其生命周期,并引入 f1
和 f2
作为元组成员的名称。
从 C++17 开始,您可以使用结构化绑定(参见其他答案)。
在 C++17(C++11 和 C++14)之前,您可以使用带有两个单独声明的 std::get()
auto f1 = std::get<0>(res);
auto f2 = std::get<1>(res);
并且,是的:在这两种情况下,您必须同时声明和定义变量[编辑:在 C++20 之前都是如此;自 C++20 以来不一定为真]
因为可以获得f1
和f2
的类型,所以加倍使用std::get()
using type_f1 = std::remove_reference_t<decltype((std::get<0>(res)))>;
using type_f2 = std::remove_reference_t<decltype((std::get<1>(res)))>;
或者,也许更好,使用 std::tuple_element
using type_f1 = std::tuple_element_t<0, decltype(res)>;
using type_f2 = std::tuple_element_t<1, decltype(res)>;
但这不允许在未定义的情况下声明 f1
和 f2
type_f1 f1; // compilation error (before C++20) !!!
type_f2 f2; // compilation error (before C++20) !!!
因为 lambdas 类型缺少 [编辑:在 C++20 之前] 默认构造函数。
编辑:正如 Nathan Oliver 所指出的(谢谢!),从 C++20 开始,具有空捕获列表的 lambda 已启用默认构造函数。
所以,从C++20开始,编译以下代码
#include <tuple>
#include <iostream>
auto fn ()
{ return std::make_tuple(
[]() { std::cout << "ran 1" << std::endl; },
[]() { std::cout << "ran 2" << std::endl; }); }
int main()
{
auto res = fn();
std::tuple_element_t<0u, decltype(res)> f1;
std::tuple_element_t<1u, decltype(res)> f2;
f1 = std::get<0u>(res);
f2 = std::get<1u>(res);
f1();
f2();
}