Why is there no piecewise tuple construction?

后端 未结 3 1494
天命终不由人
天命终不由人 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 12:07

    I'm not sure why it's not there. Previously, I thought that the implementation wouldn't be possible, given the current varadic template syntax, but I realized that it can be done if it's broken into pieces.

    If they had defined an interface like this:

    template
    tuple(piecewise_construct, T&&... t);
    

    And made it a requirement that the arguments are something that you can use std::get to access the arguments (basically, tuples, pairs, arrays). There would have to be extra checks to verify there isn't a mismatch between the number of arguments given and the number of elements in the tuple.

    Edit: This problem has been bothering me since I read it. And I've created the following class, it is derived from std::tuple, and has no data members, so you can assign it to the tuple and the slicing is harmless. The current version requires that the elements be moveable or copyable, as it creates a temporary and then inserts that into the tuple. If you were a tuple implementer, it should be possible to eliminate even that move.

    namespace detail
    {
    template
    struct index {
        typedef index next;
    };
    template
    struct build_index {
        typedef typename build_index::type::next type;
    };
    
    template<>
    struct build_index<0> {
        typedef index<> type;
    };
    
    template
    struct tuple_index {
        typedef typename build_index<
                std::tuple_size::type>::value>::type type;
    
    };
    }
    template
    class piecewise_tuple: public std::tuple
    {
        typedef std::tuple base_type;
    
        template
        static typename std::tuple_element::type 
        construct(std::tuple&& args, detail::index)
        {
            typedef typename std::tuple_element::type result_type;
            return result_type(std::get(std::move(args))...);
        }
    
        template
        piecewise_tuple(detail::index, ArgTuple&& element_args)
        : base_type( construct( std::get(std::forward(element_args)),
                     typename detail::tuple_index< typename std::tuple_element::type >::type >::type() )...)
        {
    
        }
    
    public:
    
        piecewise_tuple() = default;
    
        // For non-piecewise constructors, forward them
        template
        piecewise_tuple(Args&&... args) : base_type(std::forward(args)...) {}
    
    
        template
        piecewise_tuple(std::piecewise_construct_t, T&&... args) :
        piecewise_tuple(typename detail::tuple_index::type(),    
                        std::forward_as_tuple(std::forward(args)...))
        {
    
        }
    
    
    };
    
    // Usage example
    int main()
    {
       int i = 5;
       std::unique_ptr up(new int(0));
    
       piecewise_tuple, double, std::unique_ptr, int& >
       p(std::piecewise_construct,
        std::forward_as_tuple(1,2),
        std::forward_as_tuple(4.3),
        std::forward_as_tuple(std::move(up)),
        std::forward_as_tuple(i));
       return 0;
    }
    

提交回复
热议问题