0

I have a class derived from vector, and its data elements hold structs. My problem is that when I attempt to use swap or any other method of moving the structs from one element to another I get errors. Here is my class and the struct:

#ifndef PRIQUEUE
#define PRIQUEUE

#include "PriQueueError.h"
#include <vector>
using std::vector;

const int EMPTY_QUEUE = 1;

template <class T>
struct qElem
{
    T Data;
    int Priority;
    qElem(T data, int priority) :Data(data), Priority(priority){};
};

template <class T, class T2>
class PriQueue : public vector<T2>
{
public:
    PriQueue(){}
    PriQueue(T data, int priority);
    void enqueue(T data, int priority);
    T dequeue() throw(PriQueueError);
    T qPeek() throw(PriQueueError);
    int qSize();
};


template <class T, class T2>
PriQueue<T, T2>::PriQueue(T data, int priority)
{
    this->enqueue(data, priority);
}
template <class T, class T2>
void PriQueue<T, T2>::enqueue(T data, int priority)
{
    qElem<T> tmp1(data, priority);
    this->push_back(tmp1);
    bool flag(false);

    if (this->qSize() > 1)
    {
        for (int i = this->qSize() - 1; i > 0 || flag == false; i--)
        {
            flag = true;
            if (tmp1.Priority < tmp2.Priority)
            {
                std::swap(this[i], this[i-1]);
                flag = false;
            }
        }
    }
}
template <class T, class T2>
T PriQueue<T, T2>::dequeue() throw(PriQueueError)
{
    if (this->empty())
        throw PriQueueError("Empty Queue!");

    T tmp = this->qPeek();
    this->pop_back();
    return tmp;
}
template <class T, class T2>
T PriQueue<T, T2>::qPeek() throw(PriQueueError)
{
    if (this->empty())
        throw PriQueueError("Empty Queue!");

    qElem<T> tmpStruct = this->back();
    T tmpData = tmpStruct.Data;
    return tmpData;
}
template <class T, class T2>
int PriQueue<T, T2>::qSize()
{
    return this->size();
}

#endif

The enqueue function is a bit messy because of the constant changes I have made to it to make it work. Everywhere I read it says that to access the data member of the vector you would just use nameofclass[index].member or this[index].member. In my main when I create an instance of the class (qInt) I can access the struct using qInt[index].Data, but I cannot via this[index].Data. When I am inside enqueue and try to swap(this[index], this[anotherIndex]) it errors. When I try pull up the information on this[0] and this[1] inside the debugger watch window which should give me the first and second index location of the vector, it tells me that everything is inside this[0]. I am lost on what im doing here, my class is derived from vector and therefore should act like a vector I thought, but it seems to not be doing that at all.

Stephen
  • 25
  • 7
  • NB. using `throw` specifiers is considered bad style these days, [see here](http://stackoverflow.com/questions/88573/should-i-use-an-exception-specifier-in-c) and [here](http://stackoverflow.com/questions/12833241/difference-between-c03-throw-specifier-c11-noexcept) for why – M.M Dec 22 '14 at 01:34
  • Thank you for the mention and I have read some of the reasons why they are not a good idea, but this is a class assignment I am doing and they are required in this lab. – Stephen Dec 22 '14 at 01:36

1 Answers1

3

Deriving from vector (or any other standard container) is a bad idea. They're designed to be class members ; you should make a member variable of type vector<T2> instead. The derivation doesn't gain anything, but it does introduce problems (slicing, deleting through base class pointer, awkward syntax in your member functions, etc).

Your immediate issue is that this is a pointer, so instead of this[0] you need (*this)[0], or this->operator[](0).

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
M.M
  • 138,810
  • 21
  • 208
  • 365
  • I am deriving because this is an assignment from a class and deriving from vector is part of the requirements. If possible I would not be deriving from vector since it works as a poor queue (I would assume using a different container like list, etc would do my job better). I shall try what you mentioned though, thanks. – Stephen Dec 22 '14 at 01:35
  • @Stephen swapping an object with itself doesn't make sense anyway (maybe you meant `i` and `i-1` rather than `0`, or something?). Also you unnecessarily make a copy with `qElem tmp2 = this->at(i - 1);` ; use a reference instead. – M.M Dec 22 '14 at 01:37
  • 2
    @Stephen `deriving from vector is part of the requirements.` You have a terrible instructor, unless this is an assignment on how not to use the standard library. – user657267 Dec 22 '14 at 01:39
  • Yes I know, that is the messiness that I mentioned where my code is a bit jumbled up. I know I meant to use i and i-1, the code was still at 0 and 1 as I tried to figure out why the hell the data members would not swap under any circumstance. I just cannot seem to get pointers very well. – Stephen Dec 22 '14 at 01:40
  • Its C++ lv2 at my college, the professor likes to make us use simple shit before going into the libarary. Im taking the data structures class next semester which is called the "lv 3" class where I assume he will finally let us use the damned library. – Stephen Dec 22 '14 at 01:41
  • 1
    @Stephen it's not about "using the library" - you *should* be using `vector`, it's just that it should be a member instead of a base class. (Well - technically vector isn't the best choice for a PQ, but I mean, you should be using vector as opposed to rolling your own vector equivalent) – M.M Dec 22 '14 at 01:43
  • @Stephen you don't need to use any pointers for this assignment; `this` is the only pointer you might have to use, and you can always convert it into a reference by doing `(*this)` . – M.M Dec 22 '14 at 01:45
  • I would assume you mean create a class and have a vector as a member holding my data instead of deriving from vector and using its built in data member. – Stephen Dec 22 '14 at 01:46
  • @Stephen you already have a class template `PriQueue`, it should have a member variable `vector items;` and you would use `items.bla` instead of `this->bla` for accessing the vector – M.M Dec 22 '14 at 01:47
  • I do not mean I have to use pointers, I mean I find it difficult to remember how to deal with pointers, this being a pointer and all. My confusion on how to use this is how I ended up getting so many errors accessing the data member. – Stephen Dec 22 '14 at 01:47
  • I have a struct called qElem that technicially would be that vector you mentioned, but I actually did that previously and was docked 75 points on my final for doing that. This is me doing a makeup final because I rose hell when he did that to me and he gave me a makeup to try again. – Stephen Dec 22 '14 at 01:48
  • @Stephen I think you misunderstand, technically a vector is a vector, not a qElem. I'm saying that in a good design, you would not derive PriQueue from anything; instead it would store the queue items in a member variable. Of course you have to comply with whatever stupid conditions are on the assignment in order to gain marks on the assignment though. – M.M Dec 22 '14 at 01:55
  • What I meant was previously I would rather have a class that has a data member that is a vector of structs called qElem, and each queue item and its priority in the queue would be housed inside the indexes of qElem, and the class would simply interact with the struct data member. That was what got me docked the 75 points. Worked correctly too -_-. – Stephen Dec 22 '14 at 01:58
  • @Stephen there's another issue; `this->push_back(tmp1);` will only work if the `PriQueue` had been instantiated with `T2 = qElem` . Without seeing the rest of your code I'm not sure if the assignment specifies that they should be able to create a PriQueue with `T2` not being a `qElem`; but if it doesn't then `T2` is redundant and if it does then `qElem tmp1` should be `T2 tmp1` and similarly for `tmp2` – M.M Dec 22 '14 at 01:59
  • T2 is instantiated as qElem, I may be able to do it differently but Im strapped for time and simply want the code to work. I understand without the rest of the code you cannot tell how I have everything else going, the reason why is I usually like to ask very specific questions here and only post what is necessary to solve my issues. I feel like im bordering on homework assistance if I post my whole code and get help outside the specific question im asking. Thank you though for mentioning that. – Stephen Dec 22 '14 at 02:03
  • @Stephen to put it another way: your code only works when `T2` is instantiated as `qElem`; if this constraint was not part of the assignment then it'd be correct for your points to be docked. (This is a separate issue to the base class / member variable issue) – M.M Dec 22 '14 at 02:06
  • The reason for the T2 thing is that in order for the whole thing to work every instance of PriQueue's vector should hold a qElem under all circumstances, so when I initialize PriQueue I do so like PriQueue>, PriQueue will never initialize with T2 being anything other then qElem. If I could have avoided using T2 and just made it so that PriQueue is always a vector of qElem that works with T types then I would have, but I do not have the time to make that adjustment and T2 was a workaround that does not go against the assignments requirements and makes the code function right. – Stephen Dec 22 '14 at 02:13
  • @Stephen if you are enforcing that `qElem` be used then it would make things simpler to get rid of T2 entirely, if that is not a part of the requirements. Should only take you 60 seconds to go through changing `T,T2` to `T` and taking out the extra argument in the code that instantiates a PriQueue. – M.M Dec 22 '14 at 02:15
  • Hold on, If I remove all instances of T2 then the initialization of my PriQueue would create a vector that holds T, which would mean I cannot set each data member as qElem, I would have to set each data member as T? – Stephen Dec 22 '14 at 02:19
  • @Stephen `vector` would be replaced by `vector< qElem >` – M.M Dec 22 '14 at 02:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/67440/discussion-between-matt-mcnabb-and-stephen). – M.M Dec 22 '14 at 02:22
  • Let me backup my project and make the change, I just finished the project and I want to see if your modification would clean it up. – Stephen Dec 22 '14 at 02:22