Add element to Custom STL Container Class

I am building a RingBuffer Container and I struggling with how I should be using pointers to interact with the underlying array and complete the necessary methods inside my class. For example

void push_back(const T& elem)
{

m_buffer[m_end] = elem;
m_end--;

}


as m_buffer is a unique_ptr so I should be able to use []

operator[] <- provides indexed access to the managed array

however I get - C2678 the error binary '[': no operator found which takes a left-hand operand of type 'std::unique_ptr<T [],std::default_delete<_Ty>>'

I get no error when using a int value but I dont have indexes just the PTRs.

or should i be using the syntax:

void push_back(const T& elem)
{
*m_end = elem;
m_end--;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

/** @brief Constructor.
	 *
	 * @param capacity Desired capacity of the RingBuffer.
	 */
	RingBuffer(std::size_t capacity)
		: m_buffer(new T[capacity + 1]),
		m_base(m_buffer.get()),
		m_limit(m_base + capacity + 1), m_begin(m_base), m_end(m_base)
	{}


private:
	// This is a special syntax for declaring a
	// std::unique_ptr that points to an array of objects in the free
	// store.
	std::unique_ptr<T[]> m_buffer;

	
	T* m_base;   // Pointer to the beginning of the array of T objects
		 // implementing the ring buffer.

	T* m_limit;  // Pointer to a location 'one beyond' the array of T
		 // objects implementing the ring buffer.  (NB: this
		 // points outside the T array, and therefore must not
		 // be dereferenced.)

	T* m_begin;  // Pointer to the slot of the T array corresponding
		 // to the begin() iterator, i.e. the same slot as
		 // m_end if the buffer is empty, otherwise the slot
		 // containing what, from the client's point of view,
		 // it the first entry in the buffer.

	T* m_end;    // Pointer to the slot of the T array corresponding
		 // to the end() iterator, i.e. the same slot as
		 // m_begin if the buffer is empty, otherwise the slot
		 // one beyond (wrapping around if necessary) what,
		 // from the client's point of view, is the last entry
		 // in the buffer. 
Last edited on
> error binary '[': no operator found which takes a left-hand operand of type 'std::unique_ptr
¿is that the full message? quite awful if that's the case
it should complain about the argument, `m_end', that is a pointer and should be an integer.

> I get no error when using a int value but I dont have indexes just the PTRs.
it's your class, design it as you like
you may store the index, or you may use the pointer directly

as you have now, m_buffer and m_base have the same function.


> *m_end = elem;
> m_end--;
¿what if you go before m_base?
IMHO index is easier ... location= (location+1)%size will circle thru easily.

That said I believe its not the [] operator but some sort of syntax problem that I don't see.
I am working from a skeleton class, I should be able to implement a working container from this skeleton ( learning assignment ).

> it's your class, design it as you like
you may store the index, or you may use the pointer directly

How can I use the pointer directly?

If the ring buffer object has just been initialized. m_begin, m_end are both pointing to the start of the array which is empty. What is the correct syntax to add an element to the array to which m_end is pointing and then adjust the poistion of pointer for the next call of pop_front()?

> *m_end = elem;
> m_end--;
¿what if you go before m_base?

undefined behavior? not sure if I follow your question



essentially am I understanding the purpose these pointers correctly, pointing them at areas of the array, making changes and then adjusting the position as needed


Last edited on
exactly. and the lines between an index and pointer blur in c++. honestly an index in an array is just (start of memory location + index*sizeof type in bytes) so they are under the hood doing the exact same things: that is why either one is equally useful here.
¿how do you distinguish between a full buffer and an empty buffer?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void push_back(const T& elem)
{
   *m_end = elem; //add the element
   ++m_end; //update the pointer
   if(m_end == m_limit)
      //wrap the pointer (exercise left to the reader)
}

void push_front(const T& elem)
{
   if(m_begin == m_base)
      //wrap the pointer (exercise left to the reader)
   --m_begin;
   *m_begin = elem;
}

notice that push_back() first insert and then move the pointer
whereas push_front() first move and then insert
¿do you understand why?

for the pop_{back,front}() you just need to move the pointer in the opposite direction and wrap as appropriate.
Topic archived. No new replies allowed.