Arbitrary number of parameter assignment with template class

112 views Asked by At

I would like to implement a simple template ObjectPool kind of class. It has a fixed size vector as a member variable, which elements' are default initialized upon creation. That's done already and works fine.

The question is what is the best way to assign new elements to the member vector?

I implemented add_old_way member function, which is able to add any type of data to the ObjectPool, and works fine. My only problem is that i create an extra object which i pass to that function, and inside, i just throw it away after assignment. Waste of resources, if we are talking about giant classes.

How should i implement add_new_way function which is able to take arbitrary parameters and assign them individually to vector element?

Please note ObjectPool is templated so any kind of class can be it's type, not just Bar or Matrix2x2 as in the example below.

I don't eve now the key words here to look it up on the internet, neither if it's possible at all.

Thank you!

template <class T>
class ObjectPool
{
    vector<T> mObjects;

    ObjectPool() : mObjects(size)
    {
    }

    //that's what i could come up with to add an object to the object pool
    void add_old_way(const T& object)
    {
        ...
        mObjects[nextFreeIndex] = object;
        ...
    }

    //desired way of adding object
    void add_new_way(...)
    {
        mObjects[nextFreeIndex].param1 = param1;
        mObjects[nextFreeIndex].param2 = param2;
        ...
        mObjects[nextFreeIndex].paramN = paramN;
    }

};

class Bar
{
    Bar(int x, string s)
    {
        mX = x;
        mS = s;
    }

    int mX;
    string mS;
};


int main()
{
    ObjectPool<Bar> v;
    ObjectPool<Matrix2x2> v;

    //that's what i could come up with
    v.add_old_way(cBar(1,"asdf"));
    v.add_old_way(cMatrix2x2(1,2,3,4));

    //desired way of adding object
    v.add_new_way(1,"asdf");
    v.add_new_way(1,2,3,4);

}
2

There are 2 answers

0
Miles Budnek On BEST ANSWER

Utilize move semantics and perfect forwarding to make the assignment cheap:

template <typename... Args>
void add_new_way(Args&&... args)
{
    mObjects[nextFreeIndex] = T{std::forward<Args>(args)...};
}

Live on Coliru

Since the object being assigned from is a temporary, the move-assignment operator of the object being assigned to will be invoked if it exists. This will let the object transfer ownership of any expensive-to-copy resources from the temporary to the object in the pool.

For further reading, take a look at this question: What are move semantics?

1
diametralpitch On

If using C++11 and above, to implement your add_new_way method, you can use variadic template parameters and forwarding:

template <typename... Args>
void add_new_way(Args... args) {
  mObjects.emplace_back(std::forward<Args>(args)...);
}

Then calling code can do:

v.add_new_way(arg1, arg2, ..., argN);