114 lines
3.2 KiB
C
114 lines
3.2 KiB
C
|
#ifndef YASLI_PROTOCOLS_H_
|
||
|
#define YASLI_PROTOCOLS_H_
|
||
|
|
||
|
#include <complex>
|
||
|
#include <functional>
|
||
|
#include "yasli_memory.h"
|
||
|
#include <memory.h>
|
||
|
|
||
|
namespace yasli_protocols
|
||
|
{
|
||
|
|
||
|
// Most conservative
|
||
|
template <class T>
|
||
|
struct safe_move_traits
|
||
|
{
|
||
|
static T* destructive_move(
|
||
|
T* begin,
|
||
|
T* end,
|
||
|
void* dest)
|
||
|
{
|
||
|
T* tdest = static_cast<T*>(dest);
|
||
|
typedef std::less<T*> ls;
|
||
|
assert(!ls()(tdest, end) || ls()(tdest, begin - (end - begin)));
|
||
|
tdest = /*yasli*/std::uninitialized_copy(begin, end, tdest);
|
||
|
if (yasli_nstd::is_class<T>::value)
|
||
|
{
|
||
|
for (; begin != end; ++begin)
|
||
|
{
|
||
|
begin->~T();
|
||
|
}
|
||
|
}
|
||
|
return tdest;
|
||
|
}
|
||
|
static T* nondestructive_move(
|
||
|
T* begin,
|
||
|
T* end,
|
||
|
void* dest)
|
||
|
{
|
||
|
T* d = static_cast<T*>(dest);
|
||
|
for (; begin != end; ++begin, ++d)
|
||
|
new(d) T(*begin);
|
||
|
return d;
|
||
|
}
|
||
|
static T* nondestructive_assign_move(
|
||
|
T* begin,
|
||
|
T* end,
|
||
|
T* dest)
|
||
|
{
|
||
|
if (begin <= dest && dest < end)
|
||
|
{
|
||
|
dest += end - begin;
|
||
|
T* const result = dest;
|
||
|
while (begin != end)
|
||
|
*--dest = *--end;
|
||
|
return result;
|
||
|
}
|
||
|
for (; begin != end; ++begin, ++dest)
|
||
|
*dest = *begin;
|
||
|
return dest;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
template <class T>
|
||
|
struct memmove_traits
|
||
|
{
|
||
|
static T* destructive_move(
|
||
|
T* begin,
|
||
|
T* end,
|
||
|
void* dest)
|
||
|
{
|
||
|
memmove(dest, begin, (end - begin) * sizeof(T));
|
||
|
return static_cast<T*>(dest) + (end - begin);
|
||
|
};
|
||
|
static T* nondestructive_move(
|
||
|
T* begin,
|
||
|
T* end,
|
||
|
void* dest)
|
||
|
{
|
||
|
memmove(dest, begin, (end - begin) * sizeof(T));
|
||
|
return static_cast<T*>(dest) + (end - begin);
|
||
|
}
|
||
|
static T* nondestructive_assign_move(
|
||
|
T* begin,
|
||
|
T* end,
|
||
|
T* dest)
|
||
|
{
|
||
|
yasli_nstd::destroy_range(begin, end);
|
||
|
memmove(dest, begin, (end - begin) * sizeof(T));
|
||
|
return static_cast<T*>(dest) + (end - begin);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// for nonspecialized classes, use safe_move_traits
|
||
|
template <class T>
|
||
|
struct move_traits: public
|
||
|
yasli_nstd::type_selector<yasli_nstd::is_class<T>::value == 0,
|
||
|
memmove_traits<T>,
|
||
|
safe_move_traits<T>
|
||
|
>::result
|
||
|
{};
|
||
|
|
||
|
template <class T>
|
||
|
struct move_traits<std::complex<T> >:public
|
||
|
yasli_nstd::type_selector<sizeof(std::complex<T>) == 2 * sizeof(T),
|
||
|
memmove_traits< std::complex<T> >,
|
||
|
safe_move_traits< std::complex<T> >
|
||
|
>::result
|
||
|
{
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#endif // YASLI_PROTOCOLS_H_
|