• C++11 —— 解包 tuple 参数列表


      tuple 的主要用途,就是把各种类型的参数组合成一个新的数据关联体(结构体),相当于早期的 std::pair 的泛化版本。

      组合存储是方便了,但是,对于某些特定的应用场景,解包就成了个比较麻烦的事情。为此,我查看 gcc 8.2.0 版的 STL 源码,从 functional 文件中 提取出 tuple 索引号生成的代码,并略作更名(避免冲突),得到如下 nstuple 命名空间内的代码,这其中可变参数模板类的递归构建,用得甚是精妙,值得学习。

    namespace nstuple
    {
    
        template< size_t... _Indexes >
        struct X_Index_tuple
        {
    
        };
    
        /// Builds an X_Index_tuple< 0, 1, 2, ..., _Num - 1 >.
        template< std::size_t _Num, typename _Tuple = X_Index_tuple<> >
        struct X_Build_index_tuple;
    
        template< std::size_t _Num, size_t... _Indexes >
        struct X_Build_index_tuple<_Num, X_Index_tuple< _Indexes... > >
            : X_Build_index_tuple< _Num - 1, X_Index_tuple< _Indexes..., sizeof...(_Indexes) > >
        {
    
        };
    
        template< size_t... _Indexes >
        struct X_Build_index_tuple< 0, X_Index_tuple< _Indexes... > >
        {
            typedef X_Index_tuple< _Indexes... > __type;
        };
    
    }; // namespace nstuple
    

      有了 nstuple 中的代码,我们就可以利用 std::get() 操作,轻松的解包 tuple 的各个参数了,实现的示例代码如下所示:

    #include <iostream>
    #include <tuple>
    #include <utility>
    
    namespace nstuple
    {
        // 此处省略 nstuple 的代码,与上面提到的 nstuple 命名空间内的源码一致
        // ......
    }; // namespace nstuple
    
    void test_func(int v1, int v2, float v3)
    {
        std::cout << "(v1, v2, v3) == "
                  << "("  << v1
                  << ", " << v2
                  << ", " << v3
                  << ")"  << std::endl;
    }
    
    using X_Tuple   = std::tuple< int, int, float >;
    using X_Indices = nstuple::X_Build_index_tuple< std::tuple_size< X_Tuple >::value >::__type;
    
    template< size_t... _Ind >
    void _S_Invoke(X_Tuple && xtuple, nstuple::X_Index_tuple< _Ind... >)
    {
    	// 解包 xtuple 参数,传递给 test_func() 函数调用
        test_func(std::get< _Ind >(std::move(xtuple))...);
    }
    
    int main(int argc, char * argv[])
    {
        X_Tuple xtuple{ 100, 200, 3.141593F };
        _S_Invoke(std::forward< X_Tuple >(xtuple), X_Indices());
    
        return 0;
    }
    
    
  • 相关阅读:
    Android 开发转型前端准备知识
    atom写文档技巧
    gerrit升级到16.04之后连接不到服务器
    adb shell am pm
    ArrayList和LinkedList的区别
    Android源码编译
    Android动态加载代码技术
    File 与 FileStream 文件运用
    物体在一定范围自有碰撞
    扫描二维码加载网页图片
  • 原文地址:https://www.cnblogs.com/Gaaagaa/p/12130392.html
Copyright © 2020-2023  润新知