1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11#ifndef EIGEN_STDVECTOR_H
12#define EIGEN_STDVECTOR_H
13
14#include "details.h"
15
16/**
17 * This section contains a convenience MACRO which allows an easy specialization of
18 * std::vector such that for data types with alignment issues the correct allocator
19 * is used automatically.
20 */
21#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...) \
22namespace std \
23{ \
24  template<> \
25  class vector<__VA_ARGS__, std::allocator<__VA_ARGS__> >  \
26    : public vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
27  { \
28    typedef vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > vector_base; \
29  public: \
30    typedef __VA_ARGS__ value_type; \
31    typedef vector_base::allocator_type allocator_type; \
32    typedef vector_base::size_type size_type;  \
33    typedef vector_base::iterator iterator;  \
34    explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {}  \
35    template<typename InputIterator> \
36    vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : vector_base(first, last, a) {} \
37    vector(const vector& c) : vector_base(c) {}  \
38    explicit vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \
39    vector(iterator start, iterator end) : vector_base(start, end) {}  \
40    vector& operator=(const vector& x) {  \
41      vector_base::operator=(x);  \
42      return *this;  \
43    } \
44  }; \
45}
46
47// Don't specialize if containers are implemented according to C++11
48#if !EIGEN_HAS_CXX11_CONTAINERS
49
50namespace std {
51
52#define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \
53  public:  \
54    typedef T value_type; \
55    typedef typename vector_base::allocator_type allocator_type; \
56    typedef typename vector_base::size_type size_type;  \
57    typedef typename vector_base::iterator iterator;  \
58    typedef typename vector_base::const_iterator const_iterator;  \
59    explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {}  \
60    template<typename InputIterator> \
61    vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) \
62    : vector_base(first, last, a) {} \
63    vector(const vector& c) : vector_base(c) {}  \
64    explicit vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \
65    vector(iterator start, iterator end) : vector_base(start, end) {}  \
66    vector& operator=(const vector& x) {  \
67      vector_base::operator=(x);  \
68      return *this;  \
69    }
70
71  template<typename T>
72  class vector<T,EIGEN_ALIGNED_ALLOCATOR<T> >
73    : public vector<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
74                    Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> >
75{
76  typedef vector<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
77                 Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> > vector_base;
78  EIGEN_STD_VECTOR_SPECIALIZATION_BODY
79
80  void resize(size_type new_size)
81  { resize(new_size, T()); }
82
83#if defined(_VECTOR_)
84  // workaround MSVC std::vector implementation
85  void resize(size_type new_size, const value_type& x)
86  {
87    if (vector_base::size() < new_size)
88      vector_base::_Insert_n(vector_base::end(), new_size - vector_base::size(), x);
89    else if (new_size < vector_base::size())
90      vector_base::erase(vector_base::begin() + new_size, vector_base::end());
91  }
92  void push_back(const value_type& x)
93  { vector_base::push_back(x); }
94  using vector_base::insert;
95  iterator insert(const_iterator position, const value_type& x)
96  { return vector_base::insert(position,x); }
97  void insert(const_iterator position, size_type new_size, const value_type& x)
98  { vector_base::insert(position, new_size, x); }
99#elif defined(_GLIBCXX_VECTOR) && (!(EIGEN_GNUC_AT_LEAST(4,1)))
100  /* Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&).
101   * However, this specialization is still needed to make the above EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION trick to work. */
102  void resize(size_type new_size, const value_type& x)
103  {
104    vector_base::resize(new_size,x);
105  }
106#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,2)
107  // workaround GCC std::vector implementation
108  void resize(size_type new_size, const value_type& x)
109  {
110    if (new_size < vector_base::size())
111      vector_base::_M_erase_at_end(this->_M_impl._M_start + new_size);
112    else
113      vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
114  }
115#else
116  // either GCC 4.1 or non-GCC
117  // default implementation which should always work.
118  void resize(size_type new_size, const value_type& x)
119  {
120    if (new_size < vector_base::size())
121      vector_base::erase(vector_base::begin() + new_size, vector_base::end());
122    else if (new_size > vector_base::size())
123      vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
124  }
125#endif
126  };
127}
128#endif // !EIGEN_HAS_CXX11_CONTAINERS
129
130
131#endif // EIGEN_STDVECTOR_H
132