0

Could you please point out to me what is wrong with the following template class?

#include <vector>

template <typename T, typename C>
struct pQueue{
    pQueue():currEnd(c.end()){};
    ~pQueue(){c.~vector();}
    void insert(T& t);
    void remove(T& t);
    bool find(T& t);
    T head(void);
private:
    std::vector<T> c;
    std::vector<T>::iterator currEnd;
};

The compiler isn't very happy about the std::vector<T>::iterator currEnd; line, and produces the following error messages:

error C2146: syntax error : missing ';' before identifier 'currEnd'

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

Thank you very much!

Einheri
  • 957
  • 1
  • 9
  • 22
  • [Relevant](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords). By the way, GCC and Clang give extremely straightforward errors for this. – chris Aug 27 '13 at 13:02
  • Luckily, gcc suggests the solution: http://ideone.com/tUQz2B – mfontanini Aug 27 '13 at 13:03
  • 3
    Not related to the errors, but you are explicitly invoking a destructor from `~pQueue()`. Why? Since `c` is an actual vector and not a pointer, its destructor would run anyway. – Frédéric Hamidi Aug 27 '13 at 13:04

4 Answers4

3

the compiler doesn't recognise std::vector<T>::iterator as a type. You have to tell it:

typename std::vector<T>::iterator currEnd;

typename is used as disambiguitator in templated context. It just tells the compiler that the identifier std::vector<T>::iterator is a type rather than a static member. The standard requires this in the templated context, even though in most cases the compiler could work that out even before the template parameter T has been specified.


While the above answers your question, I can only emphasize what juanchopanza has pointed out about your code. Besides, there is std::queue for you already.

Walter
  • 44,150
  • 20
  • 113
  • 196
  • It compiles indeed. But what exactly does "typename" keyword do in this context? – Einheri Aug 27 '13 at 13:04
  • @user2531913 It tells the compiler that vector::iterator is a type, and not a static member variable. – Kaz Dragon Aug 27 '13 at 13:17
  • It's a priority queue though. I can use the priority_queue, but I can't seem to figure out how to take things off it; I can also use std::set, but I guess I'd rather implement a proper one myself which does exactly what a priority queue is supposed to do. – Einheri Aug 27 '13 at 13:25
  • @user2531913 `std::priority_queue` has members `top()` to access the top element and `pop()` to remove it. `push()` and `emplace()` insert a new element (and sort the queue in log(N) time). You cannot remove others than the top element. – Walter Aug 28 '13 at 17:09
  • @Walter It's A* search, wouldn't I need to sometimes re-evaluate the same node and, if it turns out to have a shorter distance to the starting node than before, take it off the queue and insert it again? – Einheri Aug 29 '13 at 07:13
1

You need to tell the compiler the iterator is a type name, because it is a dependent name:

typename std::vector<T>::iterator currEnd;

Besides that, this class does not need a user-provided destructor. Your class definition could be simplified to this:

template <typename T>
struct pQueue
{
    pQueue() : currEnd(c.end()) {};
    void insert(const T& t);
    void remove(const T& t);
    bool find(const T& t);   // this should probably be a const method
    T head();                // this should probably be a const method
private:
    std::vector<T> c;
    typename std::vector<T>::iterator currEnd;
};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • I want to use std::remove, so that I can take things out of the priority queue without actually freeing them while keeping track of where the end of queue actually is. Thanks for pointing out the consts, I have added them in. – Einheri Aug 27 '13 at 13:21
  • @user2531913 Oh I see, so you keep an `end` iterator that isn't necessarily the end of `c`? I think I might have done something similar with a queue once... – juanchopanza Aug 27 '13 at 13:23
0

I think it should be typename std::vector<T>::iterator currEnd;.

Then the compilcater compilator compiler can figure out that iterator is actually a type and not a member (of std::vector).

user1233963
  • 1,450
  • 15
  • 41
0x26res
  • 11,925
  • 11
  • 54
  • 108
0

Just by way of addendum to the other answers:

Sadly, VisualStudio doesn't have very good error messages. You pretty much have to learn what they mean, rather than read them literally. For example:

missing ';' before identifier 'currEnd'

Is VisualStudio-ese typically means "I don't know what the identifier before currEnd is." Usually this is due to it being undefined at that point. 9 times out of 10, it will be a type/class name for a type/class that you neglected to #include the header for. In this case it looks like it was more a matter of the compiler getting confused with a template use in a template.

However, the principle stands. Had you started with, "The compiler doesn't know what the type/class before currEnd is.", you would have been on the right track.

T.E.D.
  • 44,016
  • 10
  • 73
  • 134