Why is there no piecewise tuple construction?

后端 未结 3 1492
天命终不由人
天命终不由人 2020-12-04 11:18

The standard templates std::pair and std::array are special cases of std::tuple, and it stands to reason that they should have a very

3条回答
  •  眼角桃花
    2020-12-04 11:49

    Here is my implementation of tuple piecewise (it also allow to omit values with omit "keyword"). Zero overhead (no copy/move - direct construction):

    http://coliru.stacked-crooked.com/a/6b3f9a5f843362e3

    #include 
    #include 
    #include 
    
    
    struct Omit{} omit;
    
    
    template 
    struct TupleHolder{
        using fieldT = Field;
        using nextT = TupleHolder;
    
        Field field;
        TupleHolder next;
    
        TupleHolder(){}
    
        template 
        TupleHolder(Omit, ValuesRef&& ... values)
                : next( std::forward(values)... )
        {}
    
        template 
        TupleHolder(std::index_sequence, FieldValue&& field, ValuesRef&& ... values)
                :
                field( std::get(std::forward(field))... ),
                next( std::forward(values)... )
    
        {};
    
    
        template 
        TupleHolder(FieldValue&& field, ValuesRef&& ... values)
                : TupleHolder(
                std::make_index_sequence<
                        std::tuple_size< std::decay_t >::value
                >(),
                std::forward(field),
                std::forward(values)...
        )
        {}
    
    };
    
    
    template 
    struct TupleHolder{
        using fieldT = Field;
        Field field;    // actually last
    
        TupleHolder(){}
        TupleHolder(Omit){}
    
        template 
        TupleHolder(std::index_sequence, FieldValue&& field)
                :
                field( std::get(std::forward(field))... )
        {}
    
    
        template 
        TupleHolder(FieldValue&& field)
                : TupleHolder(
                std::make_index_sequence<
                        std::tuple_size< std::decay_t >::value
                >(),
                std::forward(field)
        )
        {}
    };
    
    
    
    template 
    struct GetLoop{
        using type = typename T::nextT;
    
        constexpr static decltype(auto) get(T& data) noexcept{
            return GetLoop::get(
                    data.next
            );
        }
    
        constexpr static decltype(auto) get(const T& data) noexcept{
            return GetLoop::get(
                    data.next
            );
        }
    
    
        constexpr static decltype(auto) get(T&& data) noexcept{
            return GetLoop::get(
                    std::forward(data.next)
            );
        }
    };
    
    template 
    struct GetLoop{
        using type = typename T::fieldT;
    
        constexpr static type& get(T& data) noexcept{
            return data.field;
        }
    
        constexpr static const type& get(const T& data) noexcept{
            return data.field;
        }
    
        constexpr static type&& get(T&& data) noexcept{
            return std::forward(data.field);
        }
    };
    
    
    // ----------------------------------------------------------------------------------
    //                          F R O N T E N D
    // ----------------------------------------------------------------------------------
    
    template
    struct TuplePiecewise{
        using fieldsT = TupleHolder;
        TupleHolder data;
    
        TuplePiecewise(){}
    
       // allow copy constructor
       TuplePiecewise(TuplePiecewise& other)
                : TuplePiecewise(static_cast(other)) {}
    
    
        template 
        explicit constexpr TuplePiecewise(ValuesRef&& ... values) noexcept
                : data( std::forward(values)... ){}
    
        TuplePiecewise( const TuplePiecewise& other ) = default;
        TuplePiecewise( TuplePiecewise&& other ) = default;
    
    
        static constexpr const std::size_t size = sizeof...(FieldTypes);
    };
    
    
    template
    constexpr decltype(auto) get(TuplePiecewise &&list) noexcept {
        return GetLoop<0, index, typename TuplePiecewise::fieldsT >::get(  std::move(list.data) );
    }
    
    template
    constexpr decltype(auto) get(TuplePiecewise &list) noexcept {
        return GetLoop<0, index, typename TuplePiecewise::fieldsT >::get(  list.data );
    }
    
    template
    constexpr decltype(auto) get(const TuplePiecewise &list) noexcept {
        return GetLoop<0, index, typename TuplePiecewise::fieldsT >::get(  list.data );
    }
    

    Usage:

    TuplePiecewise< CopyTest, int&, string, int >
    list (forward_as_tuple(45,63), forward_as_tuple(i), forward_as_tuple("hghhh"), omit );
    decltype(auto) o = get<2>(list);
    cout << o;
    

    Tuple inside tuple (zero overhead):

    TuplePiecewise< string, TuplePiecewise > list4(forward_as_tuple("RRR"), forward_as_tuple(forward_as_tuple(10), forward_as_tuple(20)));
    

提交回复
热议问题