std::tuple and standard layout

前端 未结 4 2478
感情败类
感情败类 2021-02-19 05:10

If all of the members of std::tuple are of standard layout types, is that std::tuple itself standard layout? The presence of a user-defined copy-constr

4条回答
  •  不要未来只要你来
    2021-02-19 05:41

    Inspired by PotatoSwatter's answer, I've dedicated my day to creating a standard layout tuple for C++14.

    The code actually works, but is not currently suited for use as it involves undefined behaviour. Treat it as a proof-of-concept. Here's the code I ended up with:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    //get_size
    template 
    constexpr size_t get_size()
    {
        return sizeof(T_head);
    }
    
    template 
    constexpr size_t get_size()
    {
        return get_size() + get_size();
    }
    
    
    //concat
    template
    constexpr std::array concat(const std::array& a1, const std::array& a2, std::index_sequence, std::index_sequence)
    {
      return { a1[I1]..., a2[I2]... };
    }
    
    template
    constexpr std::array concat(const std::array& a1, const std::array& a2)
    {
        return concat(a1, a2, std::make_index_sequence{}, std::make_index_sequence{});
    }
    
    
    //make_index_array
    template
    constexpr std::array make_index_array()
    {
        return {T_offset};
    }
    
    template
    constexpr std::array make_index_array()
    {
        return concat(
            make_index_array(),
            make_index_array()
        );
    }
    
    template
    constexpr std::array make_index_array()
    {
        return make_index_array<0, T_args...>();
    }
    
    
    template
    using T_param = typename std::tuple_element>::type;
    
    
    template 
    struct standard_layout_tuple
    {
        static constexpr std::array index_array = make_index_array();
    
        char storage[get_size()];
    
        //Initialization
        template
        void initialize(T_val&& val)
        {
            void* place = &this->storage[index_array[T_index]];
            new(place) T_val(std::forward(val));
        }
    
        template
        void initialize(T_val&& val, T_val2&& val2, T_vals_rest&&... vals_rest)
        {
            initialize(std::forward(val));
            initialize(std::forward(val2), std::forward(vals_rest)...);
        }
    
        void initialize(T_args&&... args)
        {
            initialize<0, T_args...>(std::forward(args)...);
        }
    
        standard_layout_tuple(T_args&&... args)
        {
            initialize(std::forward(args)...);
        }
    
        //Destruction
        template
        void destroy()
        {
            T_val* place = reinterpret_cast(&this->storage[index_array[T_index]]);
            place->~T_val();
        }
    
        template
        void destroy()
        {
            destroy();
            destroy();
        }
    
        void destroy()
        {
            destroy<0, T_args...>();
        }
    
        ~standard_layout_tuple()
        {
            destroy();
        }
    
        template
        void set(T_param&& data)
        {
            T_param* ptr = reinterpret_cast*>(&this->storage[index_array[T_index]]);
            *ptr = std::forward>(data);
        }
    
        template
        T_param& get()
        {
            return *reinterpret_cast*>(&this->storage[index_array[T_index]]);
        }
    };
    
    
    int main() {
        standard_layout_tuple sltuple{5.5f, 3.4, 7, 1.22};
        sltuple.set<2>(47);
    
        std::cout << sltuple.get<0>() << std::endl;
        std::cout << sltuple.get<1>() << std::endl;
        std::cout << sltuple.get<2>() << std::endl;
        std::cout << sltuple.get<3>() << std::endl;
    
        std::cout << "is standard layout:" << std::endl;
        std::cout << std::boolalpha << std::is_standard_layout>::value << std::endl;
    
        return 0;
    }
    

    Live example: https://ideone.com/4LEnSS

    There's a few things I'm not happy with:

    • Alignment is not handled properly which means entering misaligned types will currently give you undefined behaviour
    • Not all tuple functionality is represented yet.
    • I don't think the memory management is currently exception-safe.
    • It uses tuple to determine the type for each index.
    • The overall code quality is kinda messy.
    • There might be better, more concise ways to handle some of the recursive template functions.
    • I don't fully understand everything I did. I understand the main basics, but I'm using some of the weirder syntax on good faith. Here's the most important sources I used:
      • Create N-element constexpr array in C++11
      • Lookup table with constexpr
      • c++11 constexpr flatten list of std::array into array
      • constexpr, arrays and initialization
      • template parameter packs access Nth type and Nth element

    This is not yet suitable for use as-is, really only treat it as a proof-of-concept in this state. I will probably come back to improve on some of these issues. Or, if anyone else can improve it, feel free to edit.

提交回复
热议问题