Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are initializer lists not available when changing the allocator of std::vector?

In my project I changed the used point type from Eigen::Vector2f to Eigen::Vector2d and ran into the alignment problem.

Here is a simplified version of the code:

#include <vector>
#include <Eigen/Eigen>

int main()
{
    std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}

I'm getting the following run time error:

eigen3/Eigen/src/Core/DenseStorage.h:78: Eigen::internal::plain_array<double, 2, 0, 16>::plain_array() [T = double, Size = 2, MatrixOrArrayOptions = 0, Alignment = 16]: Assertion `(reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.

As the assert-message suggested, I read about the required alignment of Fixed-size vectorizable Eigen objects. And also the subsection about STL Containers. And it seems like I have two options:

  1. use the Eigen::aligned_allocator
  2. or use the EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION macro.

Both attempts do not compile (tested with GCC 4.8.3 and Clang 3.5) because the compiler is not able to properly convert the initializer list.

Here the altered code:

#include <vector>
#include <Eigen/Eigen>
#include <Eigen/StdVector>
// EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d)

int main()
{
    std::vector<Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d>> points = { {0,0}, {0,1} };
    // std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}

GCC error output:

error: could not convert ‘{{0, 0}, {0, 1}}’ from ‘<brace-enclosed initializer list>’ to ‘std::vector<Eigen::Matrix<double, 2, 1>, Eigen::aligned_allocator<Eigen::Matrix<double, 2, 1> > >’

So I'm wondering:

  • Why are initializer lists not available when changing the allocator of the std::vector?

    • Is this because of alignment?
    • Can I somehow align the initializer list?
  • Why is the specialization version failing?

    • Are these lacking the initializer list feature?
like image 797
mic Avatar asked Jun 19 '14 16:06

mic


1 Answers

After studying the Eigen/StdVector include file (to be precise it is in Eigen/src/StlSupport/StdVector.h line 68 of version 3.2.1), it seems that the problem originates from a partial template specialization of the std::vector within this header file. This partial template specialization replaces the STL vector as soon as you use Eigen::aligned_allocator as allocator. And this specialization seems to lack the C++11 features.

In detail why this specialization is necessary apart from replacing the allocator: Before C++11 the resize function of the std::vector could take an additional parameter by value to initialize newly created elements. According to the Eigen3 Documentation passing a parameter by value discards any alignment modifiers and cannot be used with fixed-size vectorizable Eigen objects (see SIMD).

Edit: After some more testing I realized that the C++11 implementation of the std::vector does not have the above stated issue. So to resolve the alignment problem you only need to fill in the Eigen::aligned_allocator. But do not include Eigen/StdVector. Including this file will prevent you from using the C++11 implementation of std::vector since this header defines a partial specialization with Eigen::aligned_allocator as allocator.

like image 142
mic Avatar answered Oct 25 '22 07:10

mic