Is there an STL container that stores an array of elements in contiguous memory where the element size is specified at runtime?

后端 未结 3 462
青春惊慌失措
青春惊慌失措 2021-01-22 20:49

I\'m trying to create container that looks close to how my file spec works. It\'s like a vector but the type of the elements is defined by a hashtable.

If I knew the typ

3条回答
  •  佛祖请我去吃肉
    2021-01-22 21:47

    Given this code:

    typedef Toffset uint; //byte offset;
    typedef Ttype   uint; //enum of types
    typedef std::pair member;
    typedef std::unordered_map memberdefs;
    
    memberdefs itemKey; 
    itemKey["a"] = member(0, 0);
    itemKey["b"] = member(4, 1);
    itemKey["c"] = member(8, 2);
    itemKey["d"] = member(12,1);
    itemKey["e"] = member(16,3);
    itemKey["f"] = member(17,2);
    

    You could read into a char* buffer, and use a simple wrapper class. Still bug-prone and highly confusing. This demo has no iterator (though that would be simple), and requires an external buffer to stay in scope at least as long as the class does.

    class interleaved_vector {
        const char* buffer;
        size_t count;
        size_t size;
        std::shared_ptr members;
    public: 
        class dynamic_object {
            const char* buffer;
            std::shared_ptr members;
            friend interleaved_vector;
            dynamic_object(const char* buffer_, std::shared_ptr members_)
            :buffer(buffer_), members(members_)
            {}
            dynamic_object& operator=(const dynamic_object& b) = delete;
        public:
            dynamic_object(const dynamic_object& b) 
            :buffer(b.buffer), members(b.members)
            {}
            template 
            T get(const std::string& member) const {
                assert((*members)[member].second > 0); //no new members, requires pos sizes
                assert((*members)[member].second == sizeof(T));
                return *reinterpret_cast(buffer+(*members)[member].first); //technically undefined I think
            };
            template <>
            T* get(const std::string& member) const {
                assert((*members)[member].second > 0); //no new members, requires pos sizes
                assert((*members)[member].second == sizeof(T));
                return reinterpret_cast(buffer+(*members)[member].first); //technically undefined I think
            };
            void* operator[](const std::string& member) const {
                assert((*members)[member].second > 0); //no new members, requires pos sizes
                assert((*members)[member].second == sizeof(T));
                return reinterpret_cast(buffer+(*members)[member].first); //technically undefined I think
            };
        };
        interleaved_vector(const char* buffer_, size_t count_, size_t size_, const memberdefs& members_)
        :buffer(buffer_), count(count_), size(size_), members(members_) 
        {}
        dynamic_object get(size_t index) const { 
            assert(index

    This would allow code such as:

    size_t element_size = 32;
    size_t num_elements = 1000000
    char * buffer = new char[num_elements*element_size];
    /*read into buffer*/
    interleaved_vector iv(buffer, num_elements, element_size , members);
    /*interleaved_vector DOES NOT COPY BUFFER. BUFFER MUST REMAIN IN SCOPE*/
    for(int i=0; i
                                                            
提交回复
热议问题