1 
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29 
30 #pragma once
31 
32 // appleseed.foundation headers.
33 #include "foundation/utility/alignedallocator.h"
34 
35 // Standard headers.
36 #include <vector>
37 
38 namespace foundation
39 {
40 
41 //
42 // foundation::AlignedVector is a partial specialization of std::vector for
43 // the foundation::AlignedAllocator memory allocator.
44 //
45 // foundation::AlignedVector also works around a particularity in Visual Studio's
46 // implementation of the STL where std::vector::resize() takes the value of new
47 // elements by value (as it should according to C++03) instead of by constant
48 // reference (as it should according to C++11), preventing using "overly-aligned"
49 // types with std::vector.
50 //
51 // References:
52 //
53 //   std::vector of Aligned Elements
54 //   http://thetweaker.wordpress.com/2010/05/05/stdvector-of-aligned-elements/
55 //
56 //   std::vector of Aligned Elements Revisited
57 //   http://thetweaker.wordpress.com/2010/08/15/stdvector-of-aligned-elements-revisited/
58 //
59 //   StackOverflow: Self-contained, STL-compatible implementation of std::vector
60 //   http://stackoverflow.com/questions/9409591/self-contained-stl-compatible-implementation-of-stdvector
61 //
62 //   Eigen implementation of this workaround
63 //   https://bitbucket.org/eigen/eigen/src/69228ecab94b/Eigen/src/StlSupport/details.h
64 //   https://bitbucket.org/eigen/eigen/src/69228ecab94b/Eigen/src/StlSupport/StdVector.h
65 //
66 
67 template <typename T>
68 struct VectorElementWrapper
69   : public T
70 {
VectorElementWrapperVectorElementWrapper71     VectorElementWrapper() {}
VectorElementWrapperVectorElementWrapper72     VectorElementWrapper(const T& rhs) : T(rhs) {}
73 };
74 
75 #ifdef _MSC_VER
76 #define ALIGNED_VECTOR_BASE std::vector<VectorElementWrapper<T>, AlignedAllocator<VectorElementWrapper<T>>>
77 #else
78 #define ALIGNED_VECTOR_BASE std::vector<T, AlignedAllocator<T>>
79 #endif
80 
81 template <typename T>
82 class AlignedVector
83   : public ALIGNED_VECTOR_BASE
84 {
85   public:
86     typedef ALIGNED_VECTOR_BASE Base;
87 
AlignedVector()88     AlignedVector()
89     {
90     }
91 
AlignedVector(const typename Base::allocator_type & allocator)92     explicit AlignedVector(const typename Base::allocator_type& allocator)
93       : Base(allocator)
94     {
95     }
96 
AlignedVector(const typename Base::size_type count)97     explicit AlignedVector(const typename Base::size_type count)
98       : Base(count)
99     {
100     }
101 
AlignedVector(const typename Base::size_type count,const typename Base::value_type & value)102     AlignedVector(
103         const typename Base::size_type          count,
104         const typename Base::value_type&        value)
105       : Base(count, value)
106     {
107     }
108 
AlignedVector(const typename Base::size_type count,const typename Base::value_type & value,const typename Base::allocator_type & allocator)109     AlignedVector(
110         const typename Base::size_type          count,
111         const typename Base::value_type&        value,
112         const typename Base::allocator_type&    allocator)
113       : Base(count, value, allocator)
114     {
115     }
116 
AlignedVector(const Base & rhs)117     AlignedVector(const Base& rhs)
118       : Base(rhs)
119     {
120     }
121 
122     template <typename Iterator>
AlignedVector(Iterator first,Iterator last)123     AlignedVector(Iterator first, Iterator last)
124       : Base(first, last)
125     {
126     }
127 
128     template <typename Iterator>
AlignedVector(Iterator first,Iterator last,const typename Base::allocator_type & allocator)129     AlignedVector(
130         Iterator                                first,
131         Iterator                                last,
132         const typename Base::allocator_type&    allocator)
133       : Base(first, last, allocator)
134     {
135     }
136 
AlignedVector(Base && rhs)137     AlignedVector(Base&& rhs)
138       : Base(rhs)
139     {
140     }
141 };
142 
143 #undef ALIGNED_VECTOR_BASE
144 
145 }   // namespace foundation
146