adding yasli

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@215 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
syntheticpp 2005-08-27 10:22:04 +00:00
parent f994398a51
commit cf4af691c2
7 changed files with 1520 additions and 0 deletions

76
include/loki/yasli/platform.h Executable file
View file

@ -0,0 +1,76 @@
#ifndef YASLI_PLATFORM_H_
#define YASLI_PLATFORM_H_
// Most conservative
#define YASLI_HAS_EFFICIENT_MSIZE 0
#define YASLI_REALLOC_AFTER_NEW 0
#define YASLI_HAS_EXPAND 0
#include <malloc.h>
// Works on MSVC (all versions)
#if defined(_MSC_VER)
#if defined(NDEBUG)//why only if ndebug?
#undef YASLI_REALLOC_AFTER_NEW//this is not used: what is it's intention?
#define YASLI_REALLOC_AFTER_NEW 1
#undef YASLI_HAS_EFFICIENT_MSIZE
#define YASLI_HAS_EFFICIENT_MSIZE 1
#endif
// On Wintel platforms, uninit pointers can be copied
#define YASLI_UNDEFINED_POINTERS_COPYABLE 1
namespace yasli_platform
{
inline size_t msize(const void *p)
{
return _msize(const_cast<void*>(p));
}
}
#undef YASLI_HAS_EXPAND
#define YASLI_HAS_EXPAND 1
namespace yasli_platform
{
inline void* expand(const void *p, size_t s)
{
return _expand (const_cast<void*>(p), s);
}
}
#elif defined(__MINGW32_VERSION) && !defined(RC_INVOKED)
//I havinclude Malloc.h in order to find whether this library is Mingw32
//i.e. defines __MINGW32_VERSION,
//hmm, I really need to sort this out in earlier versions
//it was _STRICT_ANSI_ not RC_INVOKED but I don't know the details
#undef YASLI_HAS_EFFICIENT_MSIZE
#define YASLI_HAS_EFFICIENT_MSIZE 1
namespace yasli_platform
{
inline size_t msize(const void *p)
{
return _msize(const_cast<void*>(p));
}
}
#undef YASLI_HAS_EXPAND
#define YASLI_HAS_EXPAND 1
namespace yasli_platform
{
inline void* expand(const void *p, size_t s)
{
return _expand (const_cast<void*>(p), s);
}
}
#define YASLI_UNDEFINED_POINTERS_COPYABLE 1 //well it appears to compile ok anyway
#endif
#endif // YASLI_PLATFORM_H_

52
include/loki/yasli/random.h Executable file
View file

@ -0,0 +1,52 @@
#ifndef RANDOM_H_
#define RANDOM_H_
#include <ctime>
class Random
{
unsigned int seed_;
public:
Random(unsigned int seed = 0)
: seed_(seed ? seed : static_cast<unsigned int>(std::time(0)))
{
}
unsigned short nextShort()
{
/* Use any number from this list for "a"
18000 18030 18273 18513 18879 19074 19098 19164 19215 19584
19599 19950 20088 20508 20544 20664 20814 20970 21153 21243
21423 21723 21954 22125 22188 22293 22860 22938 22965 22974
23109 23124 23163 23208 23508 23520 23553 23658 23865 24114
24219 24660 24699 24864 24948 25023 25308 25443 26004 26088
26154 26550 26679 26838 27183 27258 27753 27795 27810 27834
27960 28320 28380 28689 28710 28794 28854 28959 28980 29013
29379 29889 30135 30345 30459 30714 30903 30963 31059 31083
*/
static const unsigned int a = 18000;
return static_cast<unsigned short>(seed_ =
a * (seed_ & 65535) +
(seed_ >> 16));
}
unsigned int nextUint()
{
return (unsigned int)nextShort() << (CHAR_BIT * sizeof(unsigned short)) |
nextShort();
}
unsigned int nextUint(unsigned int high)
{
assert(high < ULONG_MAX - 1);
++high;
const unsigned int bucket_size = ULONG_MAX / high;
unsigned int a;
do
{
a = nextUint() / bucket_size;
}
while (a >= high);
return a;
}
};
#endif // RANDOM_H_

View file

@ -0,0 +1,181 @@
#ifndef YASLI_FILL_ITERATOR_H_
#define YASLI_FILL_ITERATOR_H_
#include <iterator>
#include <cstddef>
namespace yasli_nstd
{
template <class T>
class fill_iterator_base
: public std::iterator<
std::random_access_iterator_tag,
T,
ptrdiff_t,
T*,
T&>
{
};
template <class T>
class fill_iterator_base<T&>
: public std::iterator<
std::random_access_iterator_tag,
T,
ptrdiff_t,
T*,
T&>
{
};
template <class T>
class fill_iterator : public fill_iterator_base<T>
{
T value_;
/*difference_type*/ ptrdiff_t count_;//////////////////////////////////
public:
typedef std::ptrdiff_t difference_type;
typedef typename fill_iterator_base<T>::pointer pointer;
typedef typename fill_iterator_base<T>::reference reference;
//typedef iterator_type;
fill_iterator()
{
}
explicit fill_iterator(reference value, difference_type count = 0)
: value_(value), count_(count)
{
}
template<class U>
fill_iterator(const fill_iterator<U>& rhs)
: value_(rhs.value_), count_(rhs.count_)
{
}
reference operator*() const
{
return value_;
}
pointer operator->() const
{
return &**this;
}
fill_iterator& operator++()
{
++count_;
return *this;
}
fill_iterator operator++(int)
{
fill_iterator it(*this);
++*this;
return it;
}
fill_iterator& operator--()
{
--count_;
return *this;
}
fill_iterator operator--(int)
{
fill_iterator it(*this);
--*this;
return it;
}
fill_iterator& operator+=(difference_type d)
{
count_ += d;
return *this;
}
fill_iterator operator+(difference_type d) const
{
return fill_iterator(*this) += d;
}
fill_iterator& operator-=(difference_type d)
{
count_ -= d;
return *this;
}
fill_iterator operator-(difference_type d) const
{
return fill_iterator(*this) -= d;
}
difference_type operator-(const fill_iterator<T>& rhs) const
{
return count_ - rhs.count_;
}
reference operator[](difference_type) const
{
return **this;
}
template <class T2>
bool operator==(const fill_iterator<T2>& rhs) const
{
return count_ == rhs.count_;
}
};
template <class T, class D>
inline fill_iterator<T> operator+(D lhs, const fill_iterator<T>& rhs)
{
return rhs + lhs;
}
template <class T>
inline bool operator!=(
const fill_iterator<T>& lhs,
const fill_iterator<T>& rhs)
{ // test for fill_iterator inequality
return !(lhs == rhs);
}
template <class T>
inline bool operator<(
const fill_iterator<T>& lhs,
const fill_iterator<T>& rhs)
{
return lhs.count_ < rhs.count_;
}
template <class T>
inline bool operator>(
const fill_iterator<T>& lhs,
const fill_iterator<T>& rhs)
{
return rhs < lhs;
}
template <class T>
inline bool operator<=(
const fill_iterator<T>& lhs,
const fill_iterator<T>& rhs)
{
return !(rhs < lhs);
}
template <class T>
inline bool operator>=(
const fill_iterator<T>& lhs,
const fill_iterator<T>& rhs)
{
return !(lhs < rhs);
}
} // namespace yasli_nstd
#endif

447
include/loki/yasli/yasli_memory.h Executable file
View file

@ -0,0 +1,447 @@
#ifndef YASLI_MEMORY_H_
#define YASLI_MEMORY_H_
#include "yasli_traits.h"
#include "yasli_protocols.h"//!
#include <cassert>
#include <cstddef>
#include <misc/mojo.h>//NOT A SAFE WAY TO INCLUDE IT
namespace yasli {
// 20.4.1, the default allocator:
template <class T> class allocator;
template <> class allocator<void>;
// 20.4.1.2, allocator globals
template <class T, class U>
bool operator==(const allocator<T>&, const allocator<U>&) throw()
{ return true; }
template <class T, class U>
bool operator!=(const allocator<T>&, const allocator<U>&) throw()
{ return false; }
// 20.4.2, raw storage iterator:
// @@@ not defined, use the std one @@@
//template <class OutputIterator, class T> class raw_storage_iterator;
// 20.4.3, temporary buffers:
// @@@ not defined, use the std one @@@
//template <class T>
//pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n);
// @@@ not defined, use the std one @@@
// template <class T>
// void return_temporary_buffer(T* p);
// 20.4.4, specialized algorithms:
template <class InputIterator, class ForwardIterator>
ForwardIterator
uninitialized_copy(InputIterator first, InputIterator last,
ForwardIterator result);
template <class ForwardIterator, class Size, class T>
void uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
// 20.4.5, pointers:
// @@@ not defined, use the std one @@@
// template<class X> class auto_ptr;
}
namespace yasli {
template <class T> class allocator;
// specialize for void:
template <> class allocator<void>
{
public:
typedef void* pointer;
typedef const void* const_pointer;
// reference-to-void members are impossible.
typedef void value_type;
template <class U> struct rebind { typedef allocator<U> other; };
};
template <class T> class allocator
{
public:
typedef size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
allocator() throw() {}
allocator(const allocator&) throw() {}
template <class U> allocator(const allocator<U>&) throw() {}
~allocator() throw() {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) { return &x; }
pointer allocate(size_type n, allocator<void>::const_pointer = 0)
{
return static_cast<pointer>(::operator new(n * sizeof(T)));
}
void deallocate(pointer p, size_type)
{
::operator delete(p);
}
size_type max_size() const throw()
{
return size_type(-1);
}
void construct(pointer p, const T& val)
{
new((void *) p) T(val);
}
void destroy(pointer p)
{
((T*) p)->~T();
}
};
} // namespace yasli
namespace yasli_nstd
{
template <class T> class mallocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef mallocator<U> other; };
mallocator() throw() {}
mallocator(const mallocator&) throw() {}
template <class U> mallocator(const mallocator<U>&) throw() {}
~mallocator() throw() {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) { return &x; }
pointer allocate(size_type n, yasli::allocator<void>::const_pointer = 0)
{
return static_cast<pointer>(malloc(n * sizeof(T)));
}
void deallocate(pointer p, size_type)
{
free(p);
}
size_type max_size() const throw()
{
return size_type(-1);
}
void construct(pointer p, const T& val)
{
new((void *) p) T(val);
}
void destroy(pointer p)
{
((T*) p)->~T();
}
};
//--------------destroy--------
namespace _impl
{
struct non_destroyer
{
template <class A, class T>
static void destroy(A& a, T* p, typename A::size_type n) {}
template <class ForwardIterator>
static void destroy_range(ForwardIterator b, ForwardIterator e) {}
};
struct destroyer
{
template <class A, class T>
static void destroy(A& a, T* p, typename A::size_type n)
{
const typename A::pointer p1 = p + n;
for (; p < p1; ++p) a.destroy(p);
}
template <class ForwardIterator>
static void destroy_range(ForwardIterator b, ForwardIterator e)
{
typedef typename std::iterator_traits<ForwardIterator>::value_type
value_type;
for (; b != e; ++b) (*b).~value_type();
}
};
}
template <class A, class T>
void destroy(A& a, T* p, typename A::size_type n)
{
yasli_nstd::type_selector<yasli_nstd::is_class<T>::value != 0,
_impl::destroyer,
_impl::non_destroyer
>::result::destroy(a, p, n);
}
template <class ForwardIterator>
void destroy_range(ForwardIterator b, ForwardIterator e)
{
yasli_nstd::type_selector<
yasli_nstd::is_class<typename std::iterator_traits<ForwardIterator>
::value_type>::value != 0,
_impl::destroyer,
_impl::non_destroyer
>::result::destroy_range(b, e);
}
//---------------
template <class It1, class It2>
It2 uninitialized_move(It1 b, It1 e, It2 d)
{
return mojo::uninitialized_move(b, e, d);
}
template <class A>
struct generic_allocator_traits
{
static typename A::pointer
reallocate(
A& a,
typename A::pointer b,
typename A::pointer e,
typename A::size_type newSize)
{
typename A::pointer p1 = a.allocate(newSize, b);
const typename A::size_type oldSize = e - b;
if (oldSize <= newSize) // expand
{
yasli_protocols::move_traits<typename A::value_type>::destructive_move(
b, b + oldSize, p1);
}
else // shrink
{
yasli_protocols::move_traits<typename A::value_type>::destructive_move(
b, b + newSize, p1);
yasli_nstd::destroy(a, b + newSize, oldSize - newSize);
}
a.deallocate(b, oldSize);
return p1;
}
static bool reallocate_inplace(
A& a,
typename A::pointer b,
typename A::size_type newSize)
{
return false;
}
private:
generic_allocator_traits();
};
template <class A>
struct allocator_traits : public generic_allocator_traits<A>
{
};
template <class T>
struct allocator_traits< yasli::allocator<T> >
: public generic_allocator_traits< yasli::allocator<T> >
{
#if YASLI_NEW_IS_MALLOC != 0
static bool reallocate_inplace(
A& a,
typename A::pointer b,
typename A::size_type newSize)
{
allocator_traits< yasli_nstd::mallocator<T> >
::reallocate_inplace(a, b, newSize);
}
static typename yasli::allocator<T>::pointer
reallocate(
yasli::allocator<T>& a,
typename yasli::allocator<T>::pointer b,
typename yasli::allocator<T>::pointer e,
typename yasli::allocator<T>::size_type newSize)
{
allocator_traits< yasli_nstd::mallocator<T> >
::reallocate(a, b, e, newSize);
}
#endif//yasli_new_is_malloc
};
template <class T>
struct allocator_traits< yasli_nstd::mallocator<T> >
: public generic_allocator_traits< yasli_nstd::mallocator<T> >
{
#if YASLI_HAS_EXPAND && YASLI_HAS_EFFICIENT_MSIZE
static bool reallocate_inplace(
yasli_nstd::mallocator<T>& a,
typename yasli_nstd::mallocator<T>::pointer b,
typename yasli_nstd::mallocator<T>::size_type newSize)
{
if (b == 0) return malloc(newSize);
if (newSize == 0) {free(b); return false;}
return b == yasli_platform::expand(b, newSize)
&& yasli_platform::msize(b) >= newSize;
}
#endif
static typename yasli_nstd::mallocator<T>::pointer
reallocate(
yasli_nstd::mallocator<T>& a,
typename yasli_nstd::mallocator<T>::pointer b,
typename yasli_nstd::mallocator<T>::pointer e,
typename yasli_nstd::mallocator<T>::size_type newSize)
{
if (yasli_nstd::is_memmoveable<T>::value)
{
return static_cast<T*>(realloc(b, newSize));
}
if(reallocate_inplace(a, b, newSize)) return b;
return generic_allocator_traits< yasli_nstd::mallocator<T> >::
reallocate(a, b, e, newSize);
}
};
}
namespace yasli
{
//Here is where type_selector is really much more ugly than
//enable_if.
//----------------UNINIT COPY--------
namespace _impl
{
//safe
template <class InputItr, class FwdItr>
struct uninitialized_safe_copier
{
static FwdItr execute(InputItr first, InputItr last, FwdItr result)
{
//
struct ScopeGuard
{
FwdItr begin;
FwdItr* current;
~ScopeGuard()
{
if (!current) return;
FwdItr end = *current;
typedef typename std::iterator_traits<FwdItr>::value_type T;
for (; begin != end; ++begin) (&*begin)->~T();
}
} guard = { result, &result };
for (; first != last; ++first, ++result)
new(&*result) typename std::iterator_traits<FwdItr>::value_type(*first);
// commit
return result;
}
};
template <class T>
struct uninitialized_memcopier
{
static T* execute(const T* first, const T* last, T* result)
{
yasli_nstd::is_memcopyable<T>::value;
const size_t s = last - first;
memmove(result, first, s * sizeof(T));
return result + s;
}
};
}// _impl
// @@@ TODO: specialize for yasli_nstd::fill_iterator
template <class InputItr, class FwdItr>
FwdItr uninitialized_copy(InputItr first, InputItr last, FwdItr result)
{
std::cout<<"neither\n";
return _impl::uninitialized_safe_copier<InputItr, FwdItr>::execute(first, last, result);
}
template <class T>
T* uninitialized_copy(const T* first, const T* last, T* result)
{
std::cout<<"const\n";
return yasli_nstd::type_selector<yasli_nstd::is_memcopyable<T>::value != 0,
_impl::uninitialized_memcopier<T>,
_impl::uninitialized_safe_copier<const T*, T*>
>::result::execute(first, last, result);
}
template <class T>
T* uninitialized_copy(T* first, T* last, T* result)
{
std::cout<<"non-const\n";
return uninitialized_copy(static_cast<const T*>(first),
static_cast<const T*>(last), result);
}
//-------------------------UNINIT FILL------
template <class ForwardIterator, class T>
void
uninitialized_fill(ForwardIterator first, ForwardIterator last,
const T& x)
{
struct ScopeGuard
{
ForwardIterator first;
ForwardIterator* pCrt;
~ScopeGuard()
{
if (pCrt) yasli_nstd::destroy_range(first, *pCrt);
}
} guard = { first, &first };
for (; first != last; ++first)
new(&*first) T(x);
// Commit
guard.pCrt = 0;
}
template <class T, class U>
void
uninitialized_fill(T* first, T* last, const U& x)
{
struct ScopeGuard
{
T* first;
T** pCrt;
~ScopeGuard()
{
if (pCrt) yasli_nstd::destroy_range(first, *pCrt);
}
} guard = { first, &first };
assert(first <= last);
switch ((last - first) & 7u)
{
case 0:
while (first != last)
{
new(first) T(x); ++first;
case 7: new(first) T(x); ++first;
case 6: new(first) T(x); ++first;
case 5: new(first) T(x); ++first;
case 4: new(first) T(x); ++first;
case 3: new(first) T(x); ++first;
case 2: new(first) T(x); ++first;
case 1: new(first) T(x); ++first;
assert(first <= last);
}
}
// Commit
guard.pCrt = 0;
}
}// yasli
#endif // YASLI_MEMORY_H_

View file

@ -0,0 +1,113 @@
#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_

View file

@ -0,0 +1,75 @@
#ifndef YASLI_TRAITS_H_
#define YASLI_TRAITS_H_
namespace yasli_nstd
{
/*
template <bool b, class T = void>
struct enable_if {};
template <class T>
struct enable_if<true, T> { typedef T type; };
*/
//!! TYPE SELECTORS
//Used in place of enable_if:
//not so neat or so versitile but they do compile
template<bool condition, class if_true, class if_false>
struct type_selector
{
typedef if_true result;
};
template<class if_true, class if_false>
struct type_selector<false, if_true, if_false>
{
typedef if_false result;
};
// Types for differentiating compile-time choices
typedef char (&yes_t)[1];
typedef char (&no_t)[2];
// Credit goes to Boost;
// also found in the C++ Templates book by Vandevoorde and Josuttis
//!! Wouldn't compile with these inside is_class
template <class U>
yes_t class_test(int U::*);
template <class U>
no_t class_test(...);
template <class T> struct is_class
{
enum { value = (sizeof(class_test<T>(0)) == sizeof(yes_t)) };
};
template <typename T> struct is_pointer
{
enum { value = false };
};
template <typename T> struct is_pointer<T*>
{
enum { value = true };
};
template <typename T> struct is_memcopyable
{
enum { value = int(!is_class<T>::value) };
};
template <typename T> struct is_memmoveable
{
enum { value = int(!is_class<T>::value) };
};
// For moving
enum move_t { move };
} // namespace yasli_nstd
#endif // YASLI_TRAITS_H_

576
include/loki/yasli/yasli_vector.h Executable file
View file

@ -0,0 +1,576 @@
#include "platform.h"
#include "yasli_fill_iterator.h"
#include "yasli_memory.h"
#include "yasli_traits.h"
#include "yasli_protocols.h"
#include <iterator>
#include <cassert>
#include <stdexcept>
#include <Loki/TypeManip.h>
namespace yasli
{
template <class T, class Allocator = allocator<T> >
class vector;
}
namespace yasli {
template <class T, class Allocator>
class vector
{
struct ebo : public Allocator
{
T *beg_;
ebo() {}
ebo(const Allocator& a) : Allocator(a) {}
} ebo_;
T *end_;
T *eos_;
public:
// types:
typedef vector<T, Allocator> this_type;//not standard
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef typename Allocator::pointer iterator; // See 23.1
typedef typename Allocator::const_pointer const_iterator; // See 23.1
typedef typename Allocator::size_type size_type; // See 23.1
typedef typename Allocator::difference_type difference_type;// See 23.1
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
private:
void init_empty()
{
#if YASLI_UNDEFINED_POINTERS_COPYABLE == 1
end_ = ebo_.beg_;
eos_ = ebo_.beg_;
#else
ebo_.beg_ = 0;
end_ = 0;
eos_ = 0;
#endif
assert(empty());
}
void init_move(vector& temp)
{
ebo_ = temp.ebo_;
end_ = temp.end_;
eos_ = temp.eos_;
temp.init_empty();
}
void init_fill(size_type n, const T& value, const Allocator& a)
{
// Will avoid catch (...)
vector<T, Allocator> temp(a);
temp.insert(temp.end(), n, value);
init_move(temp);
assert(size() == n);
}
// 23.2.4.1 construct/copy/destroy:
template <class InputIterator, class looks_like_itr>
void init(InputIterator first, InputIterator last, looks_like_itr, const Allocator& a)
{
vector temp(a);
temp.insert(temp.end(), first, last);
init_move(temp);
}
template <class non_iterator>
void init(non_iterator n, non_iterator datum, Loki::Int2Type<false>,
const Allocator& a)
{
init_fill((size_type)n, (const T&)datum, a);
}
public:
vector()
{
init_empty();
}
explicit vector(const Allocator& a)
: ebo_(a)
{
init_empty();
}
explicit vector(size_type n, const T& value = T(),
const Allocator& a = Allocator())
{
init_fill(n, value, a);
}
//!! avoid enable_if
template <class InputIterator>
vector(InputIterator first, InputIterator last, const Allocator& a = Allocator())
{
init(first, last, Loki::Int2Type<
yasli_nstd::is_class<InputIterator>::value ||
yasli_nstd::is_pointer<InputIterator>::value >(), a);
}
public:
vector(const vector<T,Allocator>& x)
{
vector temp(x.begin(), x.end(), x.ebo_);
init_move(temp);
}
~vector()
{
yasli_nstd::destroy(ebo_, ebo_.beg_, size());
const size_type c = capacity();
if (c != 0) ebo_.deallocate(ebo_.beg_, c);
}
// Note pass by value
vector<T,Allocator>& operator=(vector<T,Allocator> temp)
{
temp.swap(*this);
return *this;
}
template <class InputIterator>
void assign(InputIterator first, InputIterator last)
{
assign_pre_impl(first, last, Loki::Int2Type<yasli_nstd::
is_class<InputIterator>::value||yasli_nstd::
is_pointer<InputIterator>::value>());
}
private://-------ASSIGN IMPLEMENTATION
template <class InputIterator, class looks_like_itr>
void assign_pre_impl(InputIterator first, InputIterator last, looks_like_itr)
{
assign_impl(first, last,
std::iterator_traits<InputIterator>::iterator_category());
}
template <class InputIterator>
void assign_pre_impl(InputIterator n, InputIterator datum, Loki::Int2Type<false>)
{
assign((size_type) n, (const T&) datum);
}
template <class InputIterator>
void assign_impl(InputIterator first, InputIterator last, std::input_iterator_tag)
{
for (iterator i = begin(); i != end(); ++i, ++first)
{
if (first == last)
{
resize(i - begin());
return;
}
*i = *first;
}
// we filled up the vector, now insert the rest
insert(end(), first, last);
}
template <class RanIt>
void assign_impl(RanIt first, RanIt last, std::random_access_iterator_tag)
{
const typename std::iterator_traits<RanIt>::difference_type d =
last - first;
assert(d >= 0);
size_type newSize = size_type(d);
assert(newSize == d); // no funky iterators
reserve(newSize);
if (newSize >= size())
{
const size_t delta = newSize - size();
RanIt i = last - delta;
copy(first, i, ebo_.beg_);
insert(end(), i, last);
}
else
{
copy(first, last, ebo_.beg_);
resize(newSize);
}
assert(size() == newSize);
}
public:
void assign(size_type n, const T& u)
{
const size_type s = size();
if (n <= s)
{
T* const newEnd = ebo_.beg_ + n;
fill(ebo_.beg_, newEnd, u);
yasli_nstd::destroy(ebo_, newEnd, s - n);
end_ = newEnd;
}
else
{
reserve(n);
T* const newEnd = ebo_.beg_ + n;
fill(ebo_.beg_, end_, u);
uninitialized_fill(end_, newEnd, u);
end_ = newEnd;
}
assert(size() == n);
assert(empty() || front() == back());
}
allocator_type get_allocator() const
{
return ebo_;
}
// iterators:
iterator begin() { return ebo_.beg_; }
const_iterator begin() const { return ebo_.beg_; }
iterator end() { return end_; }
const_iterator end() const { return end_; }
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
// 23.2.4.2 capacity:
size_type size() const { return end_ - ebo_.beg_; }
size_type max_size() const { return ebo_.max_size(); }
void resize(size_type sz, T c = T())
{
const size_type oldSz = size();
if (oldSz >= sz)
{
erase(ebo_.beg_ + sz, end_);
}
else
{
reserve(sz);
uninitialized_fill(end_, end_ + (sz - oldSz), c);
end_ = ebo_.beg_ + sz;
}
assert(size() == sz);
}
private:
template<class is>
void resize_impl(size_type sz, T c)
{
}
public:
size_type capacity() const
{
return eos_ - ebo_.beg_;
}
bool empty() const
{
return ebo_.beg_ == end_;
}
void reserve(size_type n)
{
const size_type
s = size(),
c = capacity();
if (c >= n) return;
if (capacity() == 0)
{
ebo_.beg_ = ebo_.allocate(n);
}
else
{
ebo_.beg_ = yasli_nstd::allocator_traits<Allocator>::reallocate(
ebo_, ebo_.beg_, end_, n);
}
end_ = ebo_.beg_ + s;
eos_ = ebo_.beg_ + n;
assert(capacity() >= n);
assert(size() == s);
}
bool reserve_inplace_nstd(size_type n)
{
if (capacity() >= n) return true;
if (!yasli_nstd::allocator_traits<Allocator>::reallocate_inplace(
ebo_, ebo_.beg_, n))
{
return false;
}
eos_ = ebo_.beg_ + n;
return true;
}
// element access:
reference operator[](size_type n)
{
assert(n < size());
return ebo_.beg_[n];
}
const_reference operator[](size_type n) const
{
assert(n < size());
return ebo_.beg_[n];
}
const_reference at(size_type n) const
{
// Fix by Joseph Canedo
if (n >= size()) throw std::range_error("vector<>::at");
return ebo_.beg_[n];
}
reference at(size_type n)
{
// Fix by Joseph Canedo
if (n >= size()) throw std::range_error("vector<>::at");
return ebo_.beg_[n];
}
reference front()
{
assert(!empty());
return *ebo_.beg_;
}
const_reference front() const
{
assert(!empty());
return *ebo_.beg_;
}
reference back()
{
assert(!empty());
return end_[-1];
}
const_reference back() const
{
assert(!empty());
return end_[-1];
}
private:
void prepare_growth(size_type delta)
{
const size_type s = size();
// @@@ todo: replace magic constant with something meaningful
const size_type smallThreshold = 8;
if (s < smallThreshold)
{
reserve(std::max(smallThreshold, delta));
}
else
{
const size_type multiply = 3;
const size_type divide = 2;
const size_type suggestedSize = (s * multiply) / divide;
reserve(std::max(s + delta, suggestedSize));
}
}
public:
// 23.2.4.3 modifiers:
void push_back(const T& x)
{
if (size() == capacity())
{
prepare_growth(1);
}
new(end_) T(x);
++end_;
}
void pop_back()
{
assert(!empty());
ebo_.destroy(--end_);
}
void move_back_nstd(T& x)
{
if (size() == capacity())
{
prepare_growth(1);
}
yasli_protocols::move_traits<T>::nondestructive_move(&x, &x + 1, end_);
}
// 23.2.4.3 modifiers:
iterator insert(iterator position, const T& x)
{
// @@@ be smarter about this reservation
reserve(size() + 1);
const size_type pos = position - begin();
insert(position, (size_type)1, x);
return ebo_.beg_ + pos;
}
void insert(iterator position, size_type n, const T& x)
{
insert(position,
yasli_nstd::fill_iterator<const T&>(x),
yasli_nstd::fill_iterator<const T&>(x, n)
);
}
template <class InputIterator>
void insert(iterator position, InputIterator first, InputIterator last)
{
insert_pre_impl(position, first, last,
Loki::Int2Type<yasli_nstd::is_class<InputIterator>::value||
yasli_nstd::is_pointer<InputIterator>::value>());
}
private:
template<class InputIterator, class looks_like_iterator>
void
insert_pre_impl(iterator position, InputIterator first, InputIterator last,
looks_like_iterator)
{
insert_impl(position, first, last,
typename std::iterator_traits<InputIterator>::iterator_category());
}
template <class non_iterator>
void insert_pre_impl(iterator position, non_iterator n, non_iterator x,
Loki::Int2Type<false>)
{ //used if e.g. T is int and insert(itr, 10, 6) is called
insert(position, static_cast<size_type>(n),
static_cast<value_type>(x));
}
template <class InputIterator>
void insert_impl(iterator position,
InputIterator first, InputIterator last, std::input_iterator_tag)
{
for (; first != last; ++first)
{
position = insert(position, *first) + 1;
}
}
template <class FwdIterator>
void insert_impl(iterator position,
FwdIterator first, FwdIterator last, std::forward_iterator_tag)
{
typedef yasli_protocols::move_traits<T> mt;
const typename std::iterator_traits<FwdIterator>::difference_type
count = std::distance(first, last);
if (eos_ - end_ > count || reserve_inplace_nstd(size() + count)) // there's enough room
{
if (count > end_ - &*position)
{
// Step 1: fill the hole between end_ and position+count
FwdIterator i1 = first;
std::advance(i1, end_ - &*position);
FwdIterator i2 = i1;
std::advance(i2, &*position + count - end_);//why not i2 = first; advance(i2,count);
T* const oldEnd = end_;
end_ = copy(i1, i2, end_);
assert(end_ == &*position + count);
// Step 2: move existing data to the end
mt::nondestructive_move(
position,
oldEnd,
end_);
end_ = oldEnd + count;
// Step 3: copy in the remaining data
copy(first, i1, position);
}
else // simpler case
{
mt::nondestructive_move(
end_ - count,
end_,
end_);
end_ += count;
mt::nondestructive_assign_move(
position,
end_ - count,
position + count);
copy(first, last, position);
}
}
else
{
vector<T, Allocator> temp(ebo_);
temp.reserve(size() + count);
// The calls below won't cause infinite recursion
// because they will fall on the other branch
// of the if statement
temp.insert(temp.end(), begin(), position);
temp.insert(temp.end(), first, last);
temp.insert(temp.end(), position, end());
assert(temp.size() == size() + count);
temp.swap(*this);
}
}
public:
iterator erase(iterator position)
{
erase(position, position + 1);
return position;
}
iterator erase(iterator first, iterator last)
{
yasli_protocols::move_traits<T>::nondestructive_assign_move(
last, end(), first);
Allocator& a = ebo_;
const size_type destroyed = last - first;
yasli_nstd::destroy(a, end_ - destroyed, destroyed);
end_ -= destroyed;
return first;
}
void swap(vector<T,Allocator>& rhs)//COULD DO THIS WITH LESS TEMPORARIES
{
std::swap(static_cast<Allocator&>(ebo_), static_cast<Allocator&>(rhs.ebo_));
std::swap(ebo_.beg_, rhs.ebo_.beg_);
std::swap(end_, rhs.end_);
std::swap(eos_, rhs.eos_);
}
void clear()
{
Allocator& a = ebo_;
yasli_nstd::destroy(a, ebo_.beg_, size());
end_ = ebo_.beg_;
}
};//vector
template <class T, class Allocator>
bool operator==(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
template <class T, class Allocator>
bool operator< (const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
template <class T, class Allocator>
bool operator!=(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
template <class T, class Allocator>
bool operator> (const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
template <class T, class Allocator>
bool operator>=(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
template <class T, class Allocator>
bool operator<=(const vector<T,Allocator>& x,
const vector<T,Allocator>& y);
// specialized algorithms:
template <class T, class Allocator>
void swap(vector<T,Allocator>& x, vector<T,Allocator>& y);
}//yasli
namespace yasli_protocols
{
template <class T, class A>
struct move_traits< yasli::vector<T, A> >:public
yasli_nstd::type_selector<
sizeof(yasli::vector<T, A>) != (3 * sizeof(T*)),
memmove_traits< std::complex<T> >,
safe_move_traits< std::complex<T> >
>::result
{
};
}