[RESOLVED] vector copy using new
Hey.
I'm wanting to fill the vector below with newed copies of each element in vec_ref and I was wondering if there is a STL algorithm that I can take advantage of?
Code:
int main()
{
std::vector<C> c_vec(10, C(1));
const std::vector<C>& vec_ref = c_vec;
std::vector<C*> new_c_vec;
// ... copy vec_ref into new_c_vec using "new"
return 0;
}
Cheers.
Re: vector copy using new
I find your question a little confusing. You say "newed copies" at the same time "of each element in vec_ref".
Re: vector copy using new
I think, a reasonable way of achieving this is to provide a clone() function for your class and then use std::transform.
Code:
class C {
// ...
virtual C* clone() { return new C(*this); }
}
Call to transform should look something like (not tested):
Code:
std::transform(c_vec.begin(), c_vec.end(),
std::back_inserter(new_c_vec),
mem_fun_ref(clone));
or, if you resize new_c_vec before like
Code:
std::transform(c_vec.begin(), c_vec.end(),
new_c_vec.begin(),
mem_fun_ref(clone));
Re: vector copy using new
Quote:
Originally Posted by treuss
I think, a reasonable way of achieving this is to provide a clone() function for your class and then use std::transform.
Code:
class C {
// ...
virtual C* clone() { return new C(*this); }
}
Call to transform should look something like (not tested):
Code:
std::transform(c_vec.begin(), c_vec.end(),
std::back_inserter(new_c_vec),
mem_fun_ref(clone));
or, if you resize new_c_vec before like
Code:
std::transform(c_vec.begin(), c_vec.end(),
new_c_vec.begin(),
mem_fun_ref(clone));
Nice idea! But in this case would it be better just to iterate through c_vec and push_back new Cs instead of creating the clone function? It won't be hard to change the classes that rely on this, but I'm just wondering which option you think is more professional.
Cheers. :thumb:
Re: vector copy using new
Please describe what you are going to do with the copied elements. Maybe it isn´t necessary to clone the vector by choosing a different approach than the one you´re implementing now.
Re: vector copy using new
Quote:
Originally Posted by GNiewerth
Please describe what you are going to do with the copied elements. Maybe it isn´t necessary to clone the vector by choosing a different approach than the one you´re implementing now.
Code:
// Update screen elements.
test_screen.Update(event_);
// Draw(blit) elements to screen.
test_screen.Draw(DE.Get_Screen());
// Draw screen.
DE.Draw_Screen();
In the real problem, they're going to be stored in a vector of base pointers (Base_XImage) which itself is stored in my Screen class. From there, each time Update or Draw gets called as above, each element in the vector of base pointers will have Update and Draw called polymorphically. The class hierarchy looks like this:
Code:
Base_XImage
XImage
XButton
Re: vector copy using new
Quote:
Originally Posted by Mybowlcut
Nice idea! But in this case would it be better just to iterate through c_vec and push_back new Cs instead of creating the clone function? It won't be hard to change the classes that rely on this, but I'm just wondering which option you think is more professional.
Basically I see three options:- A clone function and using std::transform with mem_fun_ref
- A free function for cloning and using std::transform with the free function
- Not using std::transform but writing the loop yourself and creating the clone inline inside the loop
I'm not 100% sure, I understand your last post correctly, but if C is in fact a base class, I would definitely create the clone function. Note that the function should be virtual and all derived classes should of course return a pointer to a derived class. You will soon find that the clone function has a lot of uses. Think about creating a deep copy of a vector of base class pointers. Piece of cake ;-)
Re: vector copy using new
Quote:
Originally Posted by treuss
Basically I see three options:
- A clone function and using std::transform with mem_fun_ref
- A free function for cloning and using std::transform with the free function
- Not using std::transform but writing the loop yourself and creating the clone inline inside the loop
I'm not 100% sure, I understand your last post correctly, but if C is in fact a base class, I would definitely create the clone function. Note that the function should be virtual and all derived classes should of course return a pointer to a derived class.
Do you mean like this?
Code:
class C
{
public:
C(int x_) : x(x_) {}
virtual C* clone() { return new C(*this); }
int x;
};
class D : public C
{
D(int x) : C(x) {}
virtual C* clone() { return new D(*this); }
};
Quote:
Originally Posted by treuss
You will soon find that the clone function has a lot of uses. Think about creating a deep copy of a vector of base class pointers. Piece of cake ;-)
It sounds good hey haha. Have you used this kind of function before?
Re: vector copy using new
D's override of clone() can return a D* instead. I believe this is the "covariant return type" thing.
Re: vector copy using new
What about a custom function object?
Code:
struct DrawFunc
{
Screen S_;
Event E_;
DrawFunc( Screen& s, Event& e ) : S_( s ), E_( e )
{
}
void operator()( C* pObj )
{
// do whatever you need to do with C, S_ and E_
}
}
std::vector<C*> c_vec;
for_each( c_vec.begin(), c_vec.end(), DrawFunc( theScreen, theEvent ) );
I just wrote this lines down, I´m pretty sure they won´t compile, but i hope you got the idea.
Re: vector copy using new
Quote:
Originally Posted by Mybowlcut
Do you mean like this?
Better:
Code:
virtual D* clone() { return new D(*this); }
And of course you are lacking the virtual destructor in the example.
Quote:
Originally Posted by Mybowlcut
It sounds good hey haha. Have you used this kind of function before?
Yes and I think it is a common design pattern, I just can't recall where I first read about it (Scott Meyers' probably).
Re: vector copy using new
Re: vector copy using new
Ok. I made the interface class Cloneable:
Code:
class Cloneable
{
public:
virtual ~Cloneable() {}
virtual Cloneable* Clone() = 0;
};
Then derived my base class from it:
Code:
class Base_XImage : public Drawable, public Updateable, public Cloneable
{
public:
Base_XImage();
Base_XImage(
const std::string& file_name_,
int position_x,
int position_y,
bool is_colour_key_,
SDL_Colour colour_key_ = SDL_Wrappers::colour(0,0,0));
Base_XImage(const Base_XImage& rhs);
virtual ~Base_XImage();
Base_XImage& operator=(const Base_XImage& rhs);
const std::string& Get_File_Name() const;
const SDL_Rect& Get_Position() const;
bool Is_Colour_Key() const;
const SDL_Colour& Get_Colour_Key() const;
virtual void Load() = 0;
virtual void Draw(SDL_Surface* screen) = 0;
virtual void Update(const SDL_Event& event_) = 0;
virtual Base_XImage* Clone() = 0;
protected:
std::string file_name;
SDL_Rect position;
bool is_colour_key;
SDL_Colour colour_key;
SDL_Surface* surface;
};
Then I tried to use transform with it (buttons is a vector of XButtons which derive from Base_XImage:
Code:
std::transform(buttons.begin(), buttons.end(),
std::back_inserter(elements), std::mem_fun_ref(&Base_XImage::Clone));
Code:
Error 1 error C2784: 'std::const_mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(_Result (__thiscall _Ty::* )(_Arg) const)' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 2 error C2784: 'std::const_mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(_Result (__thiscall _Ty::* )(_Arg) const)' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 3 error C2784: 'std::const_mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(_Result (__thiscall _Ty::* )(_Arg) const)' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 4 error C2914: 'std::mem_fun_ref' : cannot deduce template argument as function argument is ambiguous c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 5 error C2784: 'std::const_mem_fun_ref_t<_Result,_Ty> std::mem_fun_ref(_Result (__thiscall _Ty::* )(void) const)' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 6 error C2784: 'std::mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(_Result (__thiscall _Ty::* )(_Arg))' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 7 error C2784: 'std::mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(_Result (__thiscall _Ty::* )(_Arg))' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 8 error C2784: 'std::mem_fun1_ref_t<_Result,_Ty,_Arg> std::mem_fun_ref(_Result (__thiscall _Ty::* )(_Arg))' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 9 error C2914: 'std::mem_fun_ref' : cannot deduce template argument as function argument is ambiguous c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 10 error C2784: 'std::mem_fun_ref_t<_Result,_Ty> std::mem_fun_ref(_Result (__thiscall _Ty::* )(void))' : could not deduce template argument for 'overloaded function type' from 'overloaded function type' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Error 11 error C2780: '_OutIt std::transform(_InIt1,_InIt1,_InIt2,_OutIt,_Fn2)' : expects 5 arguments - 4 provided c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\screen.cpp 68
Anyone know what this is complaining about?
Re: vector copy using new
Beautiful error messages :rolleyes:
No idea, the call to transform looks correct. Try compiling the following (works with g++ and comeau), if that works try correcting your code accordingly. Or post a compilable sample of the problem ;)
Code:
#include <vector>
#include <algorithm>
#include <functional>
class Base
{
public:
virtual Base * clone() const = 0;
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual Derived * clone() const { return new Derived(*this); }
virtual ~Derived() {}
};
int main()
{
std::vector<Derived> v1(3);
std::vector<Base*> v2(3);
std::transform(v1.begin(), v1.end(),
v2.begin(),
std::mem_fun_ref(&Base::clone));
std::vector<Base*> v3;
std::transform(v1.begin(), v1.end(),
std::back_inserter(v3),
std::mem_fun_ref(&Base::clone));
}
EDIT: Just noticed that your clone function is not const. Don't know if that matters but it should of course be.
Re: vector copy using new
Could it be that buttons is a vector of objects whilst elements is a vector of object pointers? Unfortunately I can't really post a working example as my code uses a third party library.