How to get the begin pointer of std::vector with zero size?

Manda Rajo 141 Reputation points
2022-04-13T15:42:48.89+00:00

Hi, how to fix that error in the function begin()? I'm using Visual Studio 2015. Possibly the original source code was made on Linux or CodeBlocks IDE, and possibly it doesn't show that error?

#include "stdafx.h"
#include <vector>
#include <conio.h>

template <typename T>
struct emc_vector {
    size_t size() const { return m_data.size(); }
    T *begin() {
        return &m_data[0]; // <-- "Error: Expression vector subscript out of range" because m_data.size() is 0.
    }
    T *end() {
        if (size()) {
          //return &m_data[size()]; [error] Expression vector subscript out of range
            return &m_data[size() - 1] + 1;
        }
        else {
            return begin();
        }
    }
    void insert(T *at, const T& value = T()) {
        m_data.insert(m_data.begin() + size_t(at - begin()), value);
    }
    void push_back(const T &value) {
        m_data.push_back(value);
    }
private:
    std::vector<T> m_data;
};


int main()
{
    emc_vector<char> vec; // Its size is 0.
    //vec.push_back('a');
    vec.insert(vec.begin(), 'x'); // <-- This is the goal, but it crashes.

    _getch();
    return 0;
}
Developer technologies C++
{count} votes

2 answers

Sort by: Most helpful
  1. Viorel 122.5K Reputation points
    2022-04-13T16:52:41.1+00:00

    Check a workaround:

    T* begin( )
    {
        return size( ) ? &m_data[0] : nullptr;
    }
    

    Or use an approach that is probably more recommended:

    using iterator = typename std::vector<T>::iterator;
    
    iterator begin( )
    {
        return m_data.begin( );
    }
    
    void insert( iterator at, const T& value = T( ) )
    {
        m_data.insert( at, value );
    }
    
    1 person found this answer helpful.
    0 comments No comments

  2. Manda Rajo 141 Reputation points
    2022-04-13T18:19:18.317+00:00

    Thanks, I believe that your first method will work.

    Maybe it's not recommended to write like this (in the function end()):

    return &m_data[size() - 1] + 1; // Maybe it's not safe because +1 into a non existing item is wrong? Nobody knows.
    

    Maybe the idea from the following link is imperfect because it crashes just like I explained, https://github.com/graphitemaster/glsl-parser/blob/main/util.h

    So, I decide to use an iterator as you said one day, but for the moment, I use std::vector.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.