IMP logo
IMP Reference Guide  develop.27926d84dc,2024/04/19
The Integrative Modeling Platform
Vector.h
Go to the documentation of this file.
1 /**
2  * \file IMP/Vector.h
3  * \brief A class for storing lists of IMP items.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_CONVERTIBLE_VECTOR_H
10 #define IMPKERNEL_CONVERTIBLE_VECTOR_H
11 #include <IMP/kernel_config.h>
12 // do not include anything more from base
13 #include "Showable.h"
14 #include "Value.h"
15 #include <sstream>
16 #include <cereal/access.hpp>
17 #include "hash.h"
18 
19 #if defined(_MSC_VER) && _MSC_VER == 1500
20 # include <type_traits>
21 # include <boost/type_traits.hpp>
22 # include <boost/utility.hpp>
23 #endif
24 
25 #if IMP_COMPILER_HAS_DEBUG_VECTOR &&IMP_HAS_CHECKS >= IMP_INTERNAL
26 #include <debug/vector>
27 #else
28 #include <vector>
29 #endif
30 
31 // Use unified memory to back vectors when building with CUDA
32 #ifdef IMP_KERNEL_CUDA_LIB
33 # include <IMP/internal/UnifiedAllocator.h>
34 # define IMP_VECTOR_ALLOCATOR internal::UnifiedAllocator
35 #else
36 # define IMP_VECTOR_ALLOCATOR std::allocator
37 #endif
38 
39 IMPKERNEL_BEGIN_NAMESPACE
40 
41 //! A more \imp-like version of the \c std::vector.
42 /** Specifically this class adds functionality from \c Python arrays such as
43  - hashing
44  - output to streams
45  - use of \c +=es
46  - implicit conversion when the contents are implicitly convertible
47  - bounds checking in debug mode
48  */
49 template <class T, class Allocator = std::allocator<T>>
50 class Vector : public Value
51 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
52 #if IMP_COMPILER_HAS_DEBUG_VECTOR &&IMP_HAS_CHECKS >= IMP_INTERNAL
53  ,
54  public __gnu_debug::vector<T, Allocator>
55 #else
56  ,
57  public std::vector<T, Allocator>
58 #endif
59 #endif
60  {
61 #if IMP_COMPILER_HAS_DEBUG_VECTOR &&IMP_HAS_CHECKS >= IMP_INTERNAL
62  typedef __gnu_debug::vector<T, Allocator> V;
63 #else
64  typedef std::vector<T, Allocator> V;
65 #endif
66 
67  friend class cereal::access;
68 
69  template<class Archive> void save(Archive &ar) const {
70  size_t sz = V::size();
71  ar(sz);
72  auto it = V::begin();
73  while(sz-- > 0) {
74  ar(*it++);
75  }
76  }
77 
78  template<class Archive> void load(Archive &ar) {
79  size_t sz;
80  ar(sz);
81  V::resize(sz);
82  auto it = V::begin();
83  while(sz-- > 0) {
84  ar(*it++);
85  }
86  }
87 
88  public:
89  Vector() {}
90  explicit Vector(unsigned int sz, const T &t = T()) : V(sz, t) {}
91 #if defined(_MSC_VER) && _MSC_VER == 1500
92  template <class It>
93  Vector(It b, It e,
94  typename boost::disable_if<std::is_integral<It>::value>::type *t=0) {
95  for (It it = b; it != e; ++it) {
96  push_back(T(*it));
97  }
98  }
99  template <class VO>
100  explicit Vector(const std::vector<VO> &o) {
101  reserve(o.size());
102  for (std::vector<VO>::const_iterator it = o.begin();
103  it != o.end(); ++it) {
104  push_back(T(*it));
105  }
106  }
107 #else
108  template <class It>
109  Vector(It b, It e)
110  : V(b, e) {}
111  template <class VO>
112  explicit Vector(const std::vector<VO> &o)
113  : V(o.begin(), o.end()) {}
114 #endif
115  template <class O>
116  operator Vector<O>() const {
117  return Vector<O>(V::begin(), V::end());
118  }
119  template <class OV>
120  Vector<T> operator+=(const OV &o) {
121  V::insert(V::end(), o.begin(), o.end());
122  return *this;
123  }
124 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
125  void show(std::ostream &out = std::cout) const {
126  out << "[";
127  for (unsigned int i = 0; i < V::size(); ++i) {
128  if (i > 0) out << ", ";
129  if (i > 10) {
130  out << ",...";
131  break;
132  }
133  out << Showable(V::operator[](i));
134  }
135  out << "]";
136  }
137  operator Showable() const {
138  std::ostringstream oss;
139  show(oss);
140  return Showable(oss.str());
141  }
142  std::size_t __hash__() const {
143  return boost::hash_range(V::begin(), V::end());
144  }
145 #endif
146 };
147 
148 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
149 template <class T, class Allocator>
150 void swap(Vector<T, Allocator> &a, Vector<T, Allocator> &b) {
151  a.swap(b);
152 }
153 
154 template <class T, class Allocator>
155 inline Vector<T, Allocator> operator+(Vector<T, Allocator> ret,
156  const Vector<T, Allocator> &o) {
157  ret.insert(ret.end(), o.begin(), o.end());
158  return ret;
159 }
160 
161 #endif
162 
163 #if IMP_COMPILER_HAS_DEBUG_VECTOR &&IMP_HAS_CHECKS >= IMP_INTERNAL
164 template <class T, class Allocator>
165 inline std::size_t hash_value(const __gnu_debug::vector<T, Allocator> &t) {
166  return boost::hash_range(t.begin(), t.end());
167 }
168 #endif
169 
170 IMPKERNEL_END_NAMESPACE
171 
172 namespace cereal {
173  template <class Archive, class T, class Allocator>
174  struct specialize<Archive, IMP::Vector<T, Allocator>,
175  cereal::specialization::member_load_save> {};
176 }
177 
178 #endif /* IMPKERNEL_CONVERTIBLE_VECTOR_H */
Helper functions for implementing hashes.
Helper class to aid in output of IMP classes to streams.
A more IMP-like version of the std::vector.
Definition: Vector.h:50
Base class for a simple primitive-like type.
Definition: Value.h:23
std::ostream & show(Hierarchy h, std::ostream &out=std::cout)
Print the hierarchy using a given decorator to display each node.
Base class for a simple primitive-like type.
Helper class to aid in output of IMP classes to streams.
Definition: Showable.h:25