Click to See Complete Forum and Search --> : [RESOLVED] vector copy using new


Mybowlcut
January 28th, 2008, 08:09 AM
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?
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.

miteshpandey
January 28th, 2008, 08:56 AM
I find your question a little confusing. You say "newed copies" at the same time "of each element in vec_ref".

treuss
January 28th, 2008, 09:04 AM
I think, a reasonable way of achieving this is to provide a clone() function for your class and then use std::transform.class C {
// ...
virtual C* clone() { return new C(*this); }
}Call to transform should look something like (not tested):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 likestd::transform(c_vec.begin(), c_vec.end(),
new_c_vec.begin(),
mem_fun_ref(clone));

Mybowlcut
January 28th, 2008, 09:43 AM
I think, a reasonable way of achieving this is to provide a clone() function for your class and then use std::transform.class C {
// ...
virtual C* clone() { return new C(*this); }
}Call to transform should look something like (not tested):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 likestd::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:

GNiewerth
January 28th, 2008, 10:05 AM
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.

Mybowlcut
January 28th, 2008, 10:14 AM
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.
// 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:
Base_XImage
XImage
XButton

treuss
January 28th, 2008, 10:32 AM
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 loopI'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 ;-)

Mybowlcut
January 28th, 2008, 10:43 AM
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 loopI'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?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); }
};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?

laserlight
January 28th, 2008, 10:49 AM
D's override of clone() can return a D* instead. I believe this is the "covariant return type" thing.

GNiewerth
January 28th, 2008, 11:00 AM
What about a custom function object?


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.

treuss
January 28th, 2008, 11:18 AM
Do you mean like this?Better: virtual D* clone() { return new D(*this); }And of course you are lacking the virtual destructor in the example.
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).

treuss
January 28th, 2008, 01:36 PM
http://en.wikipedia.org/wiki/Prototype_pattern

Mybowlcut
January 29th, 2008, 12:26 AM
Ok. I made the interface class Cloneable:
class Cloneable
{
public:
virtual ~Cloneable() {}
virtual Cloneable* Clone() = 0;
};

Then derived my base class from it:
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:
std::transform(buttons.begin(), buttons.end(),
std::back_inserter(elements), std::mem_fun_ref(&Base_XImage::Clone));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?

treuss
January 29th, 2008, 04:57 AM
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 ;)

#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.

Mybowlcut
January 29th, 2008, 09:14 AM
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.

treuss
January 29th, 2008, 09:26 AM
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.No, that can't be it. As the clone function returns a pointer, the target should be a vector of pointers. As you are using mem_fun_ref, the source should be a vector of objects. Check my example.

MrViggy
January 29th, 2008, 05:26 PM
// 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:
Base_XImage
XImage
XButton
Wait, what is the vector of base pointers going to be used for? Just to have a list of drawing objects that need to be updated? If that's the case, what happens if someone alters the original object? Are you expecting to see that change in the "cloned" vector?

Viggy

Mybowlcut
January 29th, 2008, 08:00 PM
Wait, what is the vector of base pointers going to be used for? Just to have a list of drawing objects that need to be updated? If that's the case, what happens if someone alters the original object? Are you expecting to see that change in the "cloned" vector?

ViggyThe vector of base pointers holds images, buttons, etc. that can be drawn and updated, yes. I don't understand what you mean by alters the original object.void Screen::Load(const std::string& directory)
{
std::ifstream image_file;
IO::open_read_file(image_file, directory + IMAGES_FN);

const std::vector<XImage>& images =
IO::read_data<XImage, std::vector<XImage> >(image_file);

/*std::transform(images.begin(), images.end(),
std::back_inserter(elements), (std::mem_fun_ref(&Base_XImage::Clone)));*/

std::vector<XImage>::const_iterator image_it = images.begin();
for(; image_it != images.end(); ++image_it)
{
elements.push_back(new XImage(*image_it));
}

image_file.close();
std::ifstream button_file;
IO::open_read_file(button_file, directory + BUTTONS_FN);

const std::vector<XButton>& buttons =
IO::read_data<XButton, std::vector<XButton> >(button_file);

/*std::transform(buttons.begin(), buttons.end(),
std::back_inserter(elements), (std::mem_fun_ref(&Base_XImage::Clone)));*/

std::vector<XButton>::const_iterator button_it = buttons.begin();
for(; button_it != buttons.end(); ++button_it)
{
elements.push_back(new XButton(*button_it));
}

button_file.close();
std::ifstream audible_button_file;
IO::open_read_file(audible_button_file, directory + AUDIBLE_BUTTONS_FN);

const std::vector<Audible_XButton>& audible_buttons =
IO::read_data<Audible_XButton, std::vector<Audible_XButton> >(audible_button_file);

/*std::transform(audible_buttons.begin(), audible_buttons.end(),
std::back_inserter(elements), (std::mem_fun_ref(&Base_XImage::Clone)));*/

std::vector<Audible_XButton>::const_iterator audible_button_it = audible_buttons.begin();
for(; audible_button_it != audible_buttons.end(); ++audible_button_it)
{
elements.push_back(new Audible_XButton(*audible_button_it));
}

audible_button_file.close();
}That's my code... it's appalling, I know. :rolleyes: I need to sort it out so there's no duplication, but I'm trying to show you what I'm doing. If read_data could return a vector of pointers to newed objects then I'd use that instead of this whole copying thing.// Reads data from a file.
// - Requires that Object has an overloaded >> operator.
// - Returns a Container of Objects.
template <typename Object, typename Container>
Container read_data(std::istream& file)
{
Container v;

std::copy(
std::istream_iterator<Object>(file),
std::istream_iterator<Object>(),
std::back_inserter(v));

return v;
}

MrViggy
January 30th, 2008, 05:21 PM
What I mean is that your vector of base pointers is a copy of the original object. That means if some other piece of code updates the original object, you won't be drawing the object correctly.

Having said that, it looks like your code is okay. The list of original objects (the ones you are making copies of) is destroyed anyway. So, nevermind. :)

Viggy

treuss
January 31st, 2008, 03:48 AM
If I understand your problem correctly, the smartest thing to do is to read directly from the istream into a vector of pointers, something for which you would need a custom iterator. The following was quickly hacked based on the std::back_inserter in my STL implementation (thus I am not 100% sure it only uses the STL public interface and will run on any STL implementation):template<typename _Container>
class clone_back_insert_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
protected:
_Container* container;

public:
typedef _Container container_type;

explicit
clone_back_insert_iterator(_Container& __x) : container(&__x) { }

template<typename _ValueType>
clone_back_insert_iterator& operator=(_ValueType __value)
{
container->push_back(new _ValueType(__value));
return *this;
}

clone_back_insert_iterator& operator*()
{ return *this; }

clone_back_insert_iterator& operator++()
{ return *this; }

clone_back_insert_iterator operator++(int)
{ return *this; }
};

template<typename _Container>
inline clone_back_insert_iterator<_Container> clone_back_inserter(_Container& __x)
{ return clone_back_insert_iterator<_Container>(__x); }With this, you should be able to use std::copy to copy objects from any stream or container to a vector of (base class) pointers:#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;
std::copy(v1.begin(), v1.end(),
clone_back_inserter(v2));
}

Mybowlcut
February 1st, 2008, 12:42 AM
Looks great, treuss. Where did you put that code? I should put it in my own header file (not in <istream>!), shouldn't I?

treuss
February 1st, 2008, 01:57 AM
Looks great, treuss. Where did you put that code? I should put it in my own header file (not in <istream>!), shouldn't I?In its own header file and probably into some namespace as well.

Mybowlcut
February 1st, 2008, 08:33 AM
Ok.

I've got some errors from your code...
Error 1 error C4980: '__value' : use of this keyword requires /clr:oldSyntax command line option c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 19
Error 2 error C2327: 'Clone_Back_Insert_Iterator<_Container>::container' : is not a type name, static, or enumerator c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 16
Error 3 error C2065: '__x' : undeclared identifier c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 16
Error 4 error C3861: 'container': identifier not found c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 16
Error 5 error C2656: 'Clone_Back_Insert_Iterator<_Container>::clone_back_insert_iterator' : function not allowed as a bit field c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 16
Error 6 error C2071: 'Clone_Back_Insert_Iterator<_Container>::clone_back_insert_iterator' : illegal storage class c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 16
Error 7 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 16
Error 8 error C2143: syntax error : missing ';' before '&' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 19
Error 9 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 19
Error 10 error C2238: unexpected token(s) preceding ';' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 19
Error 11 error C2059: syntax error : '__value' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 19
Error 12 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 19
Error 13 error C2143: syntax error : missing ';' before '<end Parse>' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 19
Error 14 error C2334: unexpected token(s) preceding '{'; skipping apparent function body c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 26
Error 15 error C2143: syntax error : missing ';' before '&' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 28
Error 16 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 28
Error 17 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 29
Error 18 error C2988: unrecognizable template declaration/definition c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 29
Error 19 error C2059: syntax error : 'return' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 29
Error 20 error C2238: unexpected token(s) preceding ';' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 29
Error 21 error C2146: syntax error : missing ';' before identifier 'clone_back_insert_iterator' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 31
Error 22 error C2143: syntax error : missing ';' before '<' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 36
Error 23 error C2433: 'clone_back_insert_iterator' : 'inline' not permitted on data declarations c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 36
Error 24 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 36
Error 25 error C2988: unrecognizable template declaration/definition c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 36
Error 26 error C2059: syntax error : '<' c:\documents and settings\user\my documents\visual studio 2005\projects\sdl_game_engine\sdl_game_engine\clone_back_insert_iterator.h 36


What's this?
template<typename _Container>
inline clone_back_insert_iterator<_Container> clone_back_inserter(_Container& __x)
{
return clone_back_insert_iterator<_Container>(__x);
}

Also, if I were to summarise the class, what should I say? I've written this:// Template class for dynamically creating/storing objects.But it sounds too general...

Also... :rolleyes: I've got this function, and I copied it for Clone_Back_Insert_Iterator... just wondering if the second one (new one) is correct:
// Reads data from a file.
// - Requires that Object has an overloaded >> operator.
// - Returns a Container of Objects.
template <typename Object, typename Container>
Container read_data(std::istream& file)
{
Container v;

std::copy(
std::istream_iterator<Object>(file),
std::istream_iterator<Object>(),
std::back_inserter(v));

return v;
}

// Same as read_data, except stores newed objects.
template <typename Object, typename Container>
Container read_data_clone(std::istream& file)
{
Container v;
std::copy(
std::istream_iterator<Object>(file),
std::istream_iterator<Object>(),
Clone_Back_Insert_Iterator(v));
}

treuss
February 1st, 2008, 10:51 AM
Ok.

I've got some errors from your code...As mentioned, the implementation is a copy & paste from my version of the STL. Start with removing all underscores at the beginning of variable names. I am also not sure, if the new iterator has to inherit the std::iterator, so if the inheritance gives you trouble, try removing it.

What's this?
template<typename _Container>
inline clone_back_insert_iterator<_Container> clone_back_inserter(_Container& __x)
{
return clone_back_insert_iterator<_Container>(__x);
}It's the function that allows you to write clone_back_inserter(v) instead of clone_back_insert_iterator<std::vector<Object *> >(v)
Also, if I were to summarise the class, what should I say? I've written this:Insert iterator class that automatically allocates copies of the objects to be inserted on the heap.
Also... :rolleyes: I've got this function, and I copied it for Clone_Back_Insert_Iterator... just wondering if the second one (new one) is correct:
// Reads data from a file.
// - Requires that Object has an overloaded >> operator.
// - Returns a Container of Objects.
template <typename Object, typename Container>
Container read_data(std::istream& file)
{
Container v;

std::copy(
std::istream_iterator<Object>(file),
std::istream_iterator<Object>(),
std::back_inserter(v));

return v;
}

// Same as read_data, except stores newed objects.
template <typename Object, typename Container>
Container read_data_clone(std::istream& file)
{
Container v;
std::copy(
std::istream_iterator<Object>(file),
std::istream_iterator<Object>(),
Clone_Back_Insert_Iterator(v));
}As mentioned above, use clone_back_inserter(v) as third argument. Besides, there is the tiny inconvenience that you are copying into a local variable, creating a huge memory leak once the function finishes and v goes out of scope. But I'm sure you would have noticed that sooner or later ;)

Mybowlcut
February 1st, 2008, 11:07 AM
As mentioned, the implementation is a copy & paste from my version of the STL. Start with removing all underscores at the beginning of variable names. I am also not sure, if the new iterator has to inherit the std::iterator, so if the inheritance gives you trouble, try removing it.

It's the function that allows you to write clone_back_inserter(v) instead of clone_back_insert_iterator<std::vector<Object *> >(v)
Insert iterator class that automatically allocates copies of the objects to be inserted on the heap.
As mentioned above, use clone_back_inserter(v) as third argument. Besides, there is the tiny inconvenience that you are copying into a local variable, creating a huge memory leak once the function finishes and v goes out of scope. But I'm sure you would have noticed that sooner or later ;)
Ah... yes... huge memory leak. Haha! Is this a correct... correction? :p // Insert iterator class that automatically allocates copies
// of the objects to be inserted on the heap.
template <typename Object, typename Container>
Container* read_data_clone(std::istream& file)
{
Container* v = new Container;

std::copy(
std::istream_iterator<Object>(file),
std::istream_iterator<Object>(),
Clone_Back_Inserter(v));

return v;
}Or perhaps should I have a Container& as a parameter? Like I (think) I said, I'm fairly new to using new! Puns mania around here... :sick:

Ok. I've fixed up the code like you suggested:#ifndef CLONE_BACK_INSERT_ITERATOR_H
#define CLONE_BACK_INSERT_ITERATOR_H

// Template class for dynamically creating/storing objects.
template<typename Container>
class Clone_Back_Insert_Iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
protected:
Container* container;

public:
typedef Container container_type;

explicit
Clone_Back_Insert_Iterator(Container& c) : container(&c) { }

template<typename Element>
Clone_Back_Insert_Iterator& operator=(Element e)
{
container->push_back(new Element(e));
return *this;
}

Clone_Back_Insert_Iterator& operator*()
{ return *this; }

Clone_Back_Insert_Iterator& operator++()
{ return *this; }

Clone_Back_Insert_Iterator operator++(int)
{ return *this; }
};

template<typename Container>
inline Clone_Back_Insert_Iterator<Container> Clone_Back_Inserter(Container& c)
{
return Clone_Back_Insert_Iterator<Container>(c);
}

#endifJust wanting to get the final OK before I use it in my code. It compiles fine.

Cheers for your help so far... it has been very useful. :thumb:

treuss
February 1st, 2008, 11:44 AM
Or perhaps should I have a Container& as a parameter?Preferably. That way, the calling function can decide whether to create the container on the heap or on stack.
Just wanting to get the final OK before I use it in my code. It compiles fine.Looks fine to me. I'm still not sure, if inheriting from std::iterator is necessary (or recommended). But there is certainly a is-a relationship, so why not if it works.

Mybowlcut
February 3rd, 2008, 11:26 PM
Preferably. That way, the calling function can decide whether to create the container on the heap or on stack.
Looks fine to me. I'm still not sure, if inheriting from std::iterator is necessary (or recommended). But there is certainly a is-a relationship, so why not if it works.After several days of laziness and avoiding the whole thing, I got it to work. :) Thankyou! :thumb: