Sign in to follow this  
freeworld

how to create a std::vector without knowing the type of data that is in it?

Recommended Posts

freeworld    341
I got a wierd situation, I want to bea ble to create an instance of a class that has a std::vector inside it, but the class it's self never knows what the actualy value is that's in the vector, just the sizeof the data type. Is this possible?

struct MyStruct
{
    ...
};

class MYClass
{
    std::Vector<UnknownType> myVector;
}


Ultimately I want the vector to contain the MyStruct, but Mystruct can be anything. How would I define the class and be able to create the class so the vector would work normally? The reason I'm trying to do this is for my 2D renderer, I've always used a single vertex type for everything, but I've recently had the need for multiple types of vertex's some the difference only being the lack of extra data such as multiple uv coordinates or some needing color values other not. So I'm trying to figure out a way to allow for multiple types without having to hard code them into the way I sort through and process drawcalls.

Share this post


Link to post
Share on other sites
karwosts    840
No, vector doesn't work like that. There may be some boost function that can give you that kind of behavior, but not for standard vector.

If you want to include multiple types of object in a vector, you can do it through polymorphism, with the constraint that all members inherit from a base class, and that the vector only stores pointers to objects (and not the objects themselves). For example you can do this:


class A : public BaseClass {
...
}
class B : public BaseClass {
...
}

std::vector<BaseClass*> vec;
A* a = new A();
B* b = new B();
BaseClass* c = new BaseClass();
vec.push_back(a);
vec.push_back(b);
vec.push_back(c);







But you cannot just push any old thing you want into a vector.

Share this post


Link to post
Share on other sites
freeworld    341
Quote:
Original post by karwosts
No, vector doesn't work like that. There may be some boost function that can give you that kind of behavior, but not for standard vector.

If you want to include multiple types of object in a vector, you can do it through polymorphism, with the constraint that all members inherit from a base class, and that the vector only stores pointers to objects (and not the objects themselves). For example you can do this:

*** Source Snippet Removed ***


But you cannot just push any old thing you want into a vector.


That was my first thought, but I'l constantly be rebuilding the data inside the vector, and haveing to allocate memory for every element each frame seems like it would be a big hit to speed.

going with that idea though if I have a function that takes a pointer to the base class would I be able to do this.


MyFunction(baseClass*);

// call it like so
MyFunction(new derivedClass(...));

Share this post


Link to post
Share on other sites
jpetrie    13104
Quote:

That was my first thought, but I'l constantly be rebuilding the data inside the vector, and haveing to allocate memory for every element each frame seems like it would be a big hit to speed.

Forgetting for the moment if this is a true statement (it should not be, you're probably doing something wrong)... it has nothing to do with what type the vector uses, so it's a non-issue. Runtime polymorphic objects, as suggested, are what you want here -- vectors are templates, templates are compile-time concepts in C++.

Quote:

going with that idea though if I have a function that takes a pointer to the base class would I be able to do this.

Yes.

Share this post


Link to post
Share on other sites
freeworld    341
Well consider I have a list of pointers. That frame I'll use the data that is in them, then set them as 'used', and have to use 'delete' on them to free the memory. on the next frame I just start from the bottom of the list and begin to create new data ofcourse using the old pointers. I never delete the vector, but I do want to change everything that is in the vector.

The other idea I had that would go along with this, but i can't figure out how to make it work easily with one function call.

store an iterator to the list and only call 'new' when I actually have to push a pointer onto the stack, otherwise I just change the data that is in the created struct. That seems like the best way to go about it, but the problem is how to do it in one function?

if My function is

MyFunction(structPointer* sp);

how would I changed that to work with the idea?

Should I specify a size for the vector when creating the class and just create a bunch of blank structs ie

for (0 to maxSize)
push_back(new struct(...))

Then once again how do I define a function that can take the derived class as an argument without really know what it is, and be able to set the desired struct with the variables from the argument?

Share this post


Link to post
Share on other sites
jpetrie    13104
Quote:

Well consider I have a list of pointers. That frame I'll use the data that is in them, then set them as 'used', and have to use 'delete' on them to free the memory. on the next frame I just start from the bottom of the list and begin to create new data ofcourse using the old pointers. I never delete the vector, but I do want to change everything that is in the vector.

Whether or not this is a problem depends on your requirements. If you do not require polymorphic behavior from the vector elements, do not store pointers-to-T, just store T. This will reduce the allocation thrashing you require down to what the vector does itself, which can be optimized by reusing the space, and the cost is basically that of your ctors/dtors.

If you do require polymorphic behavior you cannot avoid the pointers (since you cannot store references in SC++L containers) and thus cannot avoid the allocation unless the pointers are non authoritative (stored elsewhere) -- which is a viable option.

Quote:

The other idea I had that would go along with this, but i can't figure out how to make it work easily with one function call.

store an iterator to the list and only call 'new' when I actually have to push a pointer onto the stack, otherwise I just change the data that is in the created struct. That seems like the best way to go about it, but the problem is how to do it in one function?

if My function is

MyFunction(structPointer* sp);

how would I changed that to work with the idea?

Should I specify a size for the vector when creating the class and just create a bunch of blank structs ie

for (0 to maxSize)
push_back(new struct(...))

Then once again how do I define a function that can take the derived class as an argument without really know what it is, and be able to set the desired struct with the variables from the argument?

This is all wonderfully useless information and conjecture... relatively speaking. It will be more useful for you to describe the problem you want to solve in high level terms, rather than the solution you think you need.

You've specified thus far that this has something to do with vertices in a 2D renderer. Explain in more detail; what do you want to do with these vertices, how do you want to handle them? Then we'll be able to provide better guidance.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this