Skip to main content
GameDev.net gamedev.net
🔒 Locked

Pushing pointers onto a vector

Started by Slaru Apr 5, 2005 at 9:58 PM 12 replies 1.5k views
Original Post
Slaru
Slaru
Hello, I have a little problem. I declare a vector of a templated struct like so:

template <typename T>
struct TemplatedStruct
{
    T value;
};

std::vector<TemplatedStruct*> VectorOfTemplatedStructs;
Now, when I want to add a TemaplatedStruct to the vector, I am doing it like this:

// Add item with different type depending on the case
switch (theCase)
{
case CaseNumOne:
    AddSettng<bool>(someValue);
    break;
case CaseNumTwo:
    AddSettng<int>(someValue);
...
}

// Add an item
template <typename ValType>
void AddSettng(ValType val)
{
    // Insert into VectorOfTemplatedStructs
    TemplatedStruct<ValType>* NewEntry = new TemplatedStruct<ValType>(val);
    VectorOfTemplatedStructs.push_back(NewEntry); // !! Here's the error
}
On the line where I push the the TemplatedStruct onto the vector, the compiler (VC++ 2003) complains that it can't convert my 'TemplatedStruct*' to a 'TemplatedStruct *const & '. The push_back() function of the vector takes a 'const _Ty& _Val' type. What kind of value is push_back() expecting? Thanks, Slaru
Slaru
Slaru
Drew_Benton: I tried both the & and * prefixes and neither worked. Where'd your post go to that was just there?
Drew_Benton
Drew_Benton
Yea sorry, I didn't think there was enough code to test, but then I saw there was so I deleted [embarrass]. I think what you are doing is not possible, but I can't really explain it, but like the problem is:
std::vector< TemplatedStruct*> VectorOfTemplatedStructs; It's expecting a template definition but that's not what it is getting. I think someone else could explain it bit better (Looks for Fruny)
Slaru
Slaru
If it isn't possible, I guess I will have to rethink how I am doing what I am doing (a settings manager class). The solution I came up with was really nice (using templates), but maybe I will just go back to my boring old simple settings manager. But, I will not give up yet! I will try a different way...

Thanks,
Slaru
Slaru
Slaru
About the 'std::vector': The compiler doesn't complain about the TemplatedStruct* being a template argument for the vector, but whenever I try to declare a TemplatedStruct* on the stack, it gives me an error saying not enough of the template arguments were given. I am thinking I may be able to do what I am trying to do with a void*. (I am already keeping track of what type the void* would be of)

Slaru
smart_idiot
smart_idiot
I wrote this:

#include <iostream>#include <stdexcept>class Nothing {  public: virtual ~Nothing() {}  virtual Nothing * clone() const = 0; };template <typename T> class Something: public Nothing {  protected:   friend class Anything;   T value;    public:   Something(const T &v=T()): value(v) {}   virtual Nothing * clone() const { return new Something(value); } };class Anything {  protected:   Nothing *ptr;    public:          Anything(): ptr(0) {};   template <typename T> Anything(const T &ref): ptr(new Something<T>(ref)) {}   Anything(const Anything &ref): ptr(ref.ptr->clone()) {};      template <typename T> Anything & operator = (const T &ref)    {     Nothing *temp = new Something<T>(ref);     delete ptr;     ptr = temp;     return *this;    }      Anything & operator = (const Anything &ref)    {     if(this != &ref)      {       Nothing *temp = ref.ptr->clone();       delete ptr;       ptr = temp;      }          return *this;    }      ~Anything()    {     delete ptr;    }      template <typename T> T & get()    {     Something<T> *bar = dynamic_cast<Something<T> *>(ptr);     if(bar) return bar->value;     else throw std::logic_error("Wrong type, dumbass.");    } };#include <string>int main() {  try   {    Anything anything = 42;    std::cout << anything.get<int>() << std::endl;        anything = std::string("i like cheese");    std::cout << anything.get<std::string>() << std::endl;        anything = 0;    // Will throw an exception, it isn't a string.    std::cout << anything.get<std::string>() << std::endl;   }    catch(const std::exception &error)   {    std::cout << "Oops: " << error.what() << std::endl;   }     return 0; }


Caveat: You need to know what type it's currently holding in order to get the value back. Asking for the wrong type results in an exception being thrown.

[Edited by - smart_idiot on April 5, 2005 11:55:00 PM]
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other
Slaru
Slaru
Hey smart_idiot,

Yeah, I did look at your code (contrary to what I just said if you saw that). Looks wonderful, and it applies exactly to what I need. Thanks.

Slaru
Fruny
Fruny
The problem is indeed with std::vector VectorOfTemplatedStructs;.

TemplatedStruct is not an actual type like TemplatedStruct would be: you can create a std::vector*>, or std::vector*> but not a std::vector with no specified template parameter for TemplatedStruct.

Have a look at boost::any and boost::variant. Even if you don't use the Boost library itself (hint - you should), you may learn something from their implementation.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Slaru
Slaru
Fruny,

I have looked at the boost libraries, but this was just recently, so I don't know much about the different libraries. I will have a look at your suggestions.

Slaru
JimPrice
JimPrice
Another vote of confidence for std::vector. I've used it with the Loki Object Factory code to get around objects with different constructor signatures, whilst maintaining all the nice features that the object factory stuff gives me, and it works a treat.

And if you are going to start pushing pointers into std::vectors, can I also recommend having a look at boost's smart pointers - I can't remember the last time I wrote a delete statement.

Jim.
Captain Logic
Captain Logic
Quote:
Original post by JimPrice
And if you are going to start pushing pointers into std::vectors, can I also recommend having a look at boost's smart pointers - I can't remember the last time I wrote a delete statement.

Jim.

Really? I must investigate the Boost stuff. Are there any gotchas to using their smart pointers or are they "set and forget"?
me22
me22
As long as you're nice to them ( no storing bools in the MSB or anything ), then yes, they're set and forget. weak_ptr is also wonderful.
smart_idiot
smart_idiot
IIRC boost's smart pointers break with recursive structures. For example, if A had a pointer to B and B had a pointer to A, neither would ever get deleted because each pointer would always have at least one reference.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other
JimPrice
JimPrice
Quote:

IIRC boost's smart pointers break with recursive structures. For example, if A had a pointer to B and B had a pointer to A, neither would ever get deleted because each pointer would always have at least one reference.


Yup, that's the biggie to look out for. Of course, there's nothing stopping you using a mix of smart- and dumb-pointers, so long as you use each as appropriate.

Jim.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.