template<typename OutputIterator>
void BlitSurface::ExtractFrames(OutputIterator it,
int frame_width, int frame_height,
int frames_per_row, int frames_per_column,
bool padding) const
{
SDL_Surface ** temp_surf = SDL_Ex_ExtractFrames(_surface, frame_width, frame_height, frames_per_row, frames_per_column, padding);
int surface_count = frames_per_row * frames_per_column;
for(int i=0; i<surface_count; ++i)
{
BlitSurface bs;
bs._surface = temp_surf[i];
*it = bs;
++it;
}
delete [] temp_surf;
}
我有这个功能,工作正常。唯一的问题是我不想调用复制构造函数,因为它复制整个表面,我只需要复制指针。我只想使用默认构造函数,然后将成员_surface设置为temp_surface [i],如下所示:
for(int i=0; i<surface_count; ++i)
{
it->_surface = temp_surf[i];
++it;
}
适用于普通迭代器,但不适用于插入迭代器。如何修复它以适用于两者?
答案 0 :(得分:1)
您真正想要的是移动InputIterator以与插入OutputIterator一起使用。由于C ++ 03中不存在这种情况,因此需要另一种方式来表示需要“浅”移动,而不是“深”复制。
对象本身中的简单状态标志将不起作用,因为允许实现在将对象实际放入容器之前随机复制对象。 (为了优化,你知道它不会,但不要担心调试版本。)
在我的头顶,听起来像是自定义分配器的工作。使用placement new的默认分配器copy-constructs;你可以定义一个替代构造函数,并使用placement new来调用它。
template< typename T >
struct move_traits {
typedef T must_copy_type; // does not exist in specializations
};
template< typename T >
struct move_if_possible_allocator
: std::allocator< T > {
typedef move_traits<T> traits;
// SFINAE selects this function if there is a specialization
void construct( typename traits::may_move_type *obj, T &value ) {
new( obj ) T(); // default construct
traits::move_obj( *obj, value ); // custom routine
}
// SFINAE selects this function if traits is the base template
void construct( typename traits::must_copy_type *obj, T const &value ) {
new( obj ) T( value ); // copy construct (fallback case)
}
// define rebind... exercise for the reader ;v)
};
template<>
struct move_traits< BlitSurface > {
typedef T may_move_type; // signal existence of specialization
static void move_obj( BlitSurface &out, BlitSurface &in ) {
// fill out and clear in
}
}
当然,如果某些对象实际上被复制到容器中,那么将状态添加到BlitSurface到禁用移动move_obj
是完全正常的。
答案 1 :(得分:0)
提到正在调用复制构造函数。在提供的示例中,似乎容器可能被定义为容纳BlitSurface。像std :: vector&lt; BlitSurface取代。这是我从以下几行中猜到的:
BlitSurface bs;
bs._surface = temp_surf[i];
*it = bs;
我的理解是所有std容器都会在插入时复制。从那里开始,您可以通过引用使用容器中的对象。如果你不想在BlitSurface上调用复制构造函数,那么我建议容器存储一个指向BlitSurface的指针。这样当容器在复制时插入实际复制的对象就是一个指针(不是指向的BlitSurface对象)。
BlitSurface* bs = new BlitSurface;
bs->_surface = temp_surf[i];
*it = bs;
请记住,这种方法在堆上分配(即新的),因此必须稍后显式删除内存,或者可以在容器中使用某种类型的智能指针来处理删除(std :: vector&lt; boost :: shared_ptr&lt; BlitSurface&gt;&gt;)。