使用结构化绑定来处理多重返回值

从函数返回多个值是很常见的事情,但是C++中没有最高级别语法解决方案能直接做到。开发人员必须在以下两种方法之间进行选择:要么选择通过引用参数将多个值返回给函数,要么定义包含多个值的结构题或返回std::pair或std::tuple。前两个使用命名变量,其优点是可以清楚地指示返回值的含义,但缺点是必须明确定义它们。std::pair的成员分别称为first和second,而std::tuple的未命名成员只能通过函数调用进行检索,但可以使用std::tie()复制到命名变量。这些解决方案都不算理想。

C++ 17将std::tie()的语义用法扩展到了最高级别核心语言功能中,该功能可以将元组的值解包到命名变量。 此功能称为结构化绑定。

做好准备

在本篇文章中,您应该熟悉标准实用程序类型std::pair和std::tuple以及实用程序函数std::tie()。

怎么做……

要使用支持C++ 17的编译器从一个函数返回多个值,您应该执行以下操作:

  1. 使用std::tuple作为返回类型。
  1. 使用结构化绑定将元组的值解包到命名对象中。
  1. 使用分解声明将返回的值绑定到if语句或switch语句中的变量。

这个如何起作用……

结构化绑定是一种与std::tie()相似的语言功能,只是我们不必为每个需要使用std::tie()显式解包的值定义命名变量。对于结构化绑定,我们使用auto占位符在一个定义中定义所有命名变量,以便编译器可以为每个变量推断正确的类型。

为了说明这一点,让我们考虑在std::map中插入项目的情况。insert方法返回一个std::pair,该对包含对插入的元素或阻止插入的元素的迭代器,以及一个布尔值,指示插入是否成功。下面的代码非常明确,使用second或first-> second使代码难以阅读,因为您需要不断弄清楚它们代表什么:

使用std::tie可以使前面的代码更具可读性,它将元组解压缩为单个对象(并与std::pair一起使用,因为std::tuple具有从std::pair的转换分配):

该代码不一定更简单,因为它需要预先定义该对被解压缩到的对象。同样,元组包含的元素越多,您需要定义的对象就越多,但是使用命名对象会使代码更易于阅读。

C++ 17结构化绑定将将元组元素解包到命名对象中提升到语言功能的等级。 它不需要使用std::tie(),并且在声明时初始化对象:

在上面的示例中必须使用多个块,因为不能在同一块中重新声明变量,并且结构化绑定意味着使用自动说明符进行声明。因此,如果您需要像上例中那样进行多个调用并使用结构化绑定,则必须使用不同的变量名或多个块,如上所示。替代方法是避免结构化绑定,并使用std::tie(),因为可以使用相同的变量多次调用它,因此您只需要声明一次即可。

在C++ 17中,也可以用if(init; condition)和switch(init; condition)的形式在if和switch语句中声明变量。可以将其与结构化绑定结合使用以生成更简单的代码。在下面的示例中,我们尝试将新值插入地图。调用的结果被解包为两个变量,然后插入并在初始化部分的if语句的范围内定义。if语句的条件是根据插入对象的值评估的:

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据