#ifndef YASLI_PROTOCOLS_H_ #define YASLI_PROTOCOLS_H_ #include #include #include "yasli_memory.h" #include namespace yasli_protocols { // Most conservative template struct safe_move_traits { static T* destructive_move( T* begin, T* end, void* dest) { T* tdest = static_cast(dest); typedef std::less ls; assert(!ls()(tdest, end) || ls()(tdest, begin - (end - begin))); tdest = /*yasli*/std::uninitialized_copy(begin, end, tdest); if (yasli_nstd::is_class::value) { for (; begin != end; ++begin) { begin->~T(); } } return tdest; } static T* nondestructive_move( T* begin, T* end, void* dest) { T* d = static_cast(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 struct memmove_traits { static T* destructive_move( T* begin, T* end, void* dest) { memmove(dest, begin, (end - begin) * sizeof(T)); return static_cast(dest) + (end - begin); }; static T* nondestructive_move( T* begin, T* end, void* dest) { memmove(dest, begin, (end - begin) * sizeof(T)); return static_cast(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(dest) + (end - begin); } }; // for nonspecialized classes, use safe_move_traits template struct move_traits: public yasli_nstd::type_selector::value == 0, memmove_traits, safe_move_traits >::result {}; template struct move_traits >:public yasli_nstd::type_selector) == 2 * sizeof(T), memmove_traits< std::complex >, safe_move_traits< std::complex > >::result { }; } #endif // YASLI_PROTOCOLS_H_