博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++11 —— 获取 tuple 参数列表中指定数据类型的索引位置
阅读量:4705 次
发布时间:2019-06-10

本文共 9073 字,大约阅读时间需要 30 分钟。

1. 问题背景

  在 C++11 的标准中,我们可以通过 std::get< Index >(tuple) (以常量整数值为索引号)操作 tuple 中的参数,而到了 C++14 之后的标准,新增了 std::get< Type >(tuple) (以数据类型为索引)的方式操作 tuple 中的参数。那么,若只是在 C++11 标准中,是否有办法使用 以数据类型为索引 的方式操作 tuple 中的参数呢?

2. 解决办法

  解决上面所提到的问题,其本质上,就是要解决 如何获取 tuple 参数列表中指定数据类型的索引位置 的问题。凭借这几天我积累到经验(可参看我前几篇关于 tuple 的文章),设计了以下代码中的几个模板类,有效的解决了该问题,请先详细参看如下代码:

/** * @struct X_type_index * @brief  类型索引模板:从变参列表中查找指定类型的索引位置(以 < _Fy, _Indx > 结对进行判断)。 *  * @param[in ] _Fy    : 待查找类型。 * @param[in ] _Indx  : 待查找类型在变参列表中的第几个(以 0 为起始索引)。 * @param[in ] _Ty... : 变参列表。 */template< typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index;/** * @struct X_type_index_iter * @brief  协助 X_type_index 进行 变参列表 递归遍历操作。 *  * @param[in ] _Vy    : 模板特化的参数; *                      为 true  时,转向 X_type_index_jter 继续进行递归遍历; *                      为 false 时,转回 X_type_index 继续进行递归遍历。 * @param[in ] _Fy    : 待查找类型。 * @param[in ] _Indx  : 待查找类型在变参列表中的第几个(以 0 为起始索引)。 * @param[in ] _Ty... : 变参列表。 */template< bool _Vy, typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index_iter;/** * @struct X_type_index_jter * @brief  协助 X_type_index_iter 进行 变参列表 递归遍历操作。 *  * @param[in ] _Indx  : 待查找类型在变参列表中的第几个(以 0 为起始索引); *                      为 0 时,终止递归下降,否则转回 X_type_index 继续进行递归遍历。 * @param[in ] _Fy    : 待查找类型。 * @param[in ] _Ty... : 变参列表。 */template< size_t _Indx, typename _Fy, typename... _Ty >struct X_type_index_jter;/** * @brief 终止 X_type_index_jter 递归下降。 */template< typename _Fy, typename... _Ty >struct X_type_index_jter< 0, _Fy, _Ty... >{    enum { value = 0 };};/** * @brief 转回 X_type_index 继续进行递归下降遍历。 */template< size_t _Indx, typename _Fy, typename... _Ty >struct X_type_index_jter{    enum { value = 1 + X_type_index< _Fy, _Indx - 1, _Ty... >::value };};/** * @brief 转向 X_type_index_jter 继续进行递归遍历。 */template< typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index_iter< true, _Fy, _Indx, _Ty... >{    enum { value = 0 + X_type_index_jter< _Indx, _Fy, _Ty...>::value };};/** * @brief 转回 X_type_index 继续进行递归遍历。 */template< typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index_iter< false, _Fy, _Indx, _Ty... >{    enum { value = 1 + X_type_index< _Fy, _Indx, _Ty... >::value };};/** * @brief X_type_index 递归遍历入口。 */template< typename _Fy, size_t _Indx, typename _Hy, typename... _Ty >struct X_type_index< _Fy, _Indx, _Hy, _Ty... >{    enum { value = X_type_index_iter< std::is_same< _Fy, _Hy >::value, _Fy, _Indx, _Ty... >::value };};/** * @brief X_type_index 递归遍历终结位置。 */template< typename _Fy, size_t _Indx >struct X_type_index< _Fy, _Indx >{    enum { value = 0x1FFFFFFF };};/** * @brief 从 tuple 的变参列表中查找指定类型的索引位置(以 < _Fy, _Indx > 结对进行操作)。 *  * @param [in ] _Fy   : 待查找类型。 * @param [in ] _Indx : 待查找类型在变参列表中的第几个(以 0 为起始索引)。 * @param [in ] _Ty   : tuple 的参数列表。 *  * @return size_t *         - 返回索引位置; *         - 若返回值大于等于 X_type_index< _Fy, _Indx >::value[0x1FFFFFFF] 时,表示未找到查找的类型。 */template< typename _Fy, size_t _Indx, typename... _Ty >constexpr size_t X_tuple_type_index(const std::tuple< _Ty... > &){    return X_type_index< _Fy, _Indx, _Ty... >::value;}

  以上代码中,使用 std::is_same< _Fy, _Hy >::value 判断数据类型是否一致,然后特化 X_type_index_iter<> 和 X_type_index_jter<> 这两个模板类进行递归推导操作,过程中,通过逐步累积索引值到 value 中,最后得到我们需要类型索引值。这过程,如下面的流程图所示:

type_index

3. 使用示例

  下面给出完成的测试程序代码,亦可作为使用示例的参看代码:

#include 
#include
#include
/** * @struct X_type_index * @brief 类型索引模板:从变参列表中查找指定类型的索引位置(以 < _Fy, _Indx > 结对进行判断)。 * * @param[in ] _Fy : 待查找类型。 * @param[in ] _Indx : 待查找类型在变参列表中的第几个(以 0 为起始索引)。 * @param[in ] _Ty... : 变参列表。 */template< typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index;/** * @struct X_type_index_iter * @brief 协助 X_type_index 进行 变参列表 递归遍历操作。 * * @param[in ] _Vy : 模板特化的参数; * 为 true 时,转向 X_type_index_jter 继续进行递归遍历; * 为 false 时,转回 X_type_index 继续进行递归遍历。 * @param[in ] _Fy : 待查找类型。 * @param[in ] _Indx : 待查找类型在变参列表中的第几个(以 0 为起始索引)。 * @param[in ] _Ty... : 变参列表。 */template< bool _Vy, typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index_iter;/** * @struct X_type_index_jter * @brief 协助 X_type_index_iter 进行 变参列表 递归遍历操作。 * * @param[in ] _Indx : 待查找类型在变参列表中的第几个(以 0 为起始索引); * 为 0 时,终止递归下降,否则转回 X_type_index 继续进行递归遍历。 * @param[in ] _Fy : 待查找类型。 * @param[in ] _Ty... : 变参列表。 */template< size_t _Indx, typename _Fy, typename... _Ty >struct X_type_index_jter;/** * @brief 终止 X_type_index_jter 递归下降。 */template< typename _Fy, typename... _Ty >struct X_type_index_jter< 0, _Fy, _Ty... >{ enum { value = 0 };};/** * @brief 转回 X_type_index 继续进行递归下降遍历。 */template< size_t _Indx, typename _Fy, typename... _Ty >struct X_type_index_jter{ enum { value = 1 + X_type_index< _Fy, _Indx - 1, _Ty... >::value };};/** * @brief 转向 X_type_index_jter 继续进行递归遍历。 */template< typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index_iter< true, _Fy, _Indx, _Ty... >{ enum { value = 0 + X_type_index_jter< _Indx, _Fy, _Ty...>::value };};/** * @brief 转回 X_type_index 继续进行递归遍历。 */template< typename _Fy, size_t _Indx, typename... _Ty >struct X_type_index_iter< false, _Fy, _Indx, _Ty... >{ enum { value = 1 + X_type_index< _Fy, _Indx, _Ty... >::value };};/** * @brief X_type_index 递归遍历入口。 */template< typename _Fy, size_t _Indx, typename _Hy, typename... _Ty >struct X_type_index< _Fy, _Indx, _Hy, _Ty... >{ enum { value = X_type_index_iter< std::is_same< _Fy, _Hy >::value, _Fy, _Indx, _Ty... >::value };};/** * @brief X_type_index 递归遍历终结位置。 */template< typename _Fy, size_t _Indx >struct X_type_index< _Fy, _Indx >{ enum { value = 0x1FFFFFFF };};/** * @brief 从 tuple 的变参列表中查找指定类型的索引位置(以 < _Fy, _Indx > 结对进行操作)。 * * @param [in ] _Fy : 待查找类型。 * @param [in ] _Indx : 待查找类型在变参列表中的第几个(以 0 为起始索引)。 * @param [in ] _Ty : tuple 的参数列表。 * * @return size_t * - 返回索引位置; * - 若返回值大于等于 X_type_index< _Fy, _Indx >::value[0x1FFFFFFF] 时,表示未找到查找的类型。 */template< typename _Fy, size_t _Indx, typename... _Ty >constexpr size_t X_tuple_type_index(const std::tuple< _Ty... > &){ return X_type_index< _Fy, _Indx, _Ty... >::value;}int main(int argc, char * argv[]){ using _Tuple = std::tuple< int, int, int, char, float, double >; //====================================== // 获取索引号 std::cout << "< int , 0 > : " << X_type_index< int , 0 >::value << std::endl; std::cout << "< int , 0 > : " << X_type_index< int , 0, int >::value << std::endl; std::cout << "< char , 0 > : " << X_type_index< char, 0, int, int >::value << std::endl; std::cout << "< int , 1 > : " << X_type_index< int , 1, int, int, char >::value << std::endl; std::cout << "< char , 0 > : " << X_type_index< char, 0, int, int, char, char >::value << std::endl; std::cout << "< char , 1 > : " << X_type_index< char, 1, int, int, char, char, char >::value << std::endl; std::cout << "tuple type = std::tuple< int, int, int, char, float, double >" << std::endl; std::cout << "< int , 1 > : " << X_tuple_type_index< int , 1 >(_Tuple{}) << std::endl; std::cout << "< int & , 1 > : " << X_tuple_type_index< int & , 1 >(_Tuple{}) << std::endl; std::cout << "< char , 1 > : " << X_tuple_type_index< char , 1 >(_Tuple{}) << std::endl; std::cout << "< double, 1 > : " << X_tuple_type_index< double, 1 >(_Tuple{}) << std::endl; std::cout << "< float , 1 > : " << X_tuple_type_index< float , 1 >(_Tuple{}) << std::endl; std::cout << "< void *, 1 > : " << X_tuple_type_index< void *, 1 >(_Tuple{}) << std::endl; //====================================== // 按 数据类型方式索引 tuple 的参数 _Tuple xtuple{ 100, 200, 300, 'A', 1.234F, 1.234 }; std::cout << " xtpule< 0 > = " << std::get< 0 >(xtuple) << std::endl; std::cout << " xtpule< 1 > = " << std::get< 1 >(xtuple) << std::endl; std::cout << " xtpule< 2 > = " << std::get< 2 >(xtuple) << std::endl; std::cout << " xtpule< 3 > = " << std::get< 3 >(xtuple) << std::endl; std::cout << " xtpule< 4 > = " << std::get< 4 >(xtuple) << std::endl; std::cout << " xtpule< 5 > = " << std::get< 5 >(xtuple) << std::endl; std::get< X_tuple_type_index< int , 0 >(xtuple) >(xtuple) = 101; std::get< X_tuple_type_index< int , 1 >(xtuple) >(xtuple) = 201; std::get< X_tuple_type_index< int , 2 >(xtuple) >(xtuple) = 301; std::get< X_tuple_type_index< char , 0 >(xtuple) >(xtuple) = 'B'; std::get< X_tuple_type_index< float , 0 >(xtuple) >(xtuple) = 1.245F; std::get< X_tuple_type_index< double, 0 >(xtuple) >(xtuple) = 1.236; std::cout << " xtpule< int , 0 >[0] = " << std::get< 0 >(xtuple) << std::endl; std::cout << " xtpule< int , 1 >[1] = " << std::get< 1 >(xtuple) << std::endl; std::cout << " xtpule< int , 2 >[2] = " << std::get< 2 >(xtuple) << std::endl; std::cout << " xtpule< char , 0 >[3] = " << std::get< 3 >(xtuple) << std::endl; std::cout << " xtpule< float , 0 >[4] = " << std::get< 4 >(xtuple) << std::endl; std::cout << " xtpule< double, 0 >[5] = " << std::get< 5 >(xtuple) << std::endl; //====================================== return 0;}

转载于:https://www.cnblogs.com/VxGaaagaa/p/10159723.html

你可能感兴趣的文章
UVA 116 Unidirectional TSP (白书dp)
查看>>
第三方测速工具
查看>>
数据访问 投票习题
查看>>
cnblog!i'm coming!
查看>>
使用点符号代替溢出的文本
查看>>
fatal: remote origin already exists.
查看>>
LeetCode 242. Valid Anagram
查看>>
JSP表单提交乱码
查看>>
如何适应现代雇佣关系
查看>>
团队项目(第五周)
查看>>
SQL 优化经验总结34条
查看>>
开源 视频会议 收藏
查看>>
核心J2EE模式 - 截取过滤器
查看>>
.net开源CMS
查看>>
JdbcTemplate
查看>>
第一次使用maven记录
查看>>
SharePoint服务器端对象模型 之 使用CAML进展数据查询
查看>>
Building Tablet PC Applications ROB JARRETT
查看>>
Adobe® Reader®.插件开发
查看>>
【POJ 3461】Oulipo
查看>>