Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 1 | namespace Eigen { |
| 2 | |
| 3 | /** \eigenManualPage TopicStlContainers Using STL Containers with Eigen |
| 4 | |
| 5 | \eigenAutoToc |
| 6 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 7 | \section StlContainers_summary Executive summary |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 8 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 9 | If you're compiling in \cpp17 mode only with a sufficiently recent compiler (e.g., GCC>=7, clang>=5, MSVC>=19.12), then everything is taken care by the compiler and you can stop reading. |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 10 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 11 | Otherwise, using STL containers on \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types", or classes having members of such types, requires the use of an over-aligned allocator. |
| 12 | That is, an allocator capable of allocating buffers with 16, 32, or even 64 bytes alignment. |
| 13 | %Eigen does provide one ready for use: aligned_allocator. |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 14 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 15 | Prior to \cpp11, if you want to use the `std::vector` container, then you also have to <code> \#include <Eigen/StdVector> </code>. |
| 16 | |
| 17 | These issues arise only with \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref TopicStructHavingEigenMembers "structures having such Eigen objects as member". |
| 18 | For other %Eigen types, such as Vector3f or MatrixXd, no special care is needed when using STL containers. |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 19 | |
| 20 | \section allocator Using an aligned allocator |
| 21 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 22 | STL containers take an optional template parameter, the allocator type. When using STL containers on \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types", you need tell the container to use an allocator that will always allocate memory at 16-byte-aligned (or more) locations. Fortunately, %Eigen does provide such an allocator: Eigen::aligned_allocator. |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 23 | |
| 24 | For example, instead of |
| 25 | \code |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 26 | std::map<int, Eigen::Vector4d> |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 27 | \endcode |
| 28 | you need to use |
| 29 | \code |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 30 | std::map<int, Eigen::Vector4d, std::less<int>, |
| 31 | Eigen::aligned_allocator<std::pair<const int, Eigen::Vector4d> > > |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 32 | \endcode |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 33 | Note that the third parameter `std::less<int>` is just the default value, but we have to include it because we want to specify the fourth parameter, which is the allocator type. |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 34 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 35 | \section StlContainers_vector The case of std::vector |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 36 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 37 | This section is for c++98/03 users only. \cpp11 (or above) users can stop reading here. |
| 38 | |
| 39 | So in c++98/03, the situation with `std::vector` is more complicated because of a bug in the standard (explanation below). |
| 40 | To workaround the issue, we had to specialize it for the Eigen::aligned_allocator type. |
| 41 | In practice you \b must use the Eigen::aligned_allocator (not another aligned allocator), \b and \#include <Eigen/StdVector>. |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 42 | |
| 43 | Here is an example: |
| 44 | \code |
| 45 | #include<Eigen/StdVector> |
| 46 | /* ... */ |
| 47 | std::vector<Eigen::Vector4f,Eigen::aligned_allocator<Eigen::Vector4f> > |
| 48 | \endcode |
| 49 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 50 | <span class="note">\b Explanation: The `resize()` method of `std::vector` takes a `value_type` argument (defaulting to `value_type()`). So with `std::vector<Eigen::Vector4d>`, some Eigen::Vector4d objects will be passed by value, which discards any alignment modifiers, so a Eigen::Vector4d can be created at an unaligned location. |
| 51 | In order to avoid that, the only solution we saw was to specialize `std::vector` to make it work on a slight modification of, here, Eigen::Vector4d, that is able to deal properly with this situation. |
| 52 | </span> |
| 53 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 54 | \subsection vector_spec An alternative - specializing std::vector for Eigen types |
| 55 | |
| 56 | As an alternative to the recommended approach described above, you have the option to specialize std::vector for Eigen types requiring alignment. |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 57 | The advantage is that you won't need to declare std::vector all over with Eigen::aligned_allocator. One drawback on the other hand side is that |
| 58 | the specialization needs to be defined before all code pieces in which e.g. `std::vector<Vector2d>` is used. Otherwise, without knowing the specialization |
| 59 | the compiler will compile that particular instance with the default `std::allocator` and you program is most likely to crash. |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 60 | |
| 61 | Here is an example: |
| 62 | \code |
| 63 | #include<Eigen/StdVector> |
| 64 | /* ... */ |
| 65 | EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix2d) |
| 66 | std::vector<Eigen::Vector2d> |
| 67 | \endcode |
| 68 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 69 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 70 | |
| 71 | */ |
| 72 | |
| 73 | } |