Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self-contained, STL-compatible implementation of std::vector

The implementation of std::vector that ships with Visual Studio 2010 and earlier versions has a well known particularity: the resize method has the following signature (C++03-compliant):

void resize(size_type new_size, value_type value);

instead of the C++11-compliant signature that's been used by the majority of other STL implementations (like gcc's STL or STLport) long before C++11:

void resize(size_type new_size, const value_type& value);

The problem with the first variant is that, in some situations, it will fail to compile if value_type has an alignment specification:

struct __declspec(align(64)) S { ... };
std::vector<S> v;  // error C2719: '_Val': formal parameter with __declspec(align('64')) won't be aligned

This is a well known problem with no satisfactory workaround apart from using a different implementation of std::vector.

I'm looking for a well-written, well-tested, self-contained and STL-compatible implementation of std::vector with a MIT-style licence that I could drop into my project as a container of choice for aligned types.

I considered extracting it from STLport or gcc's STL but, being fully standard-compliant, they're both large with many non-trivial dependencies.

(I would be perfectly happy with an implementation of a reasonable subset of std::vector that would only support push_back, clear, capacity, size, reserve, resize, swap and array indexing.)

Any ideas?

like image 379
François Beaune Avatar asked Feb 23 '12 08:02

François Beaune


1 Answers

The guys behind the Eigen library seem to have found a nice workaround for the problem of storing "overly-aligned types" (as Stephan T. Lavavej call them) into a std::vector as implemented in Visual Studio's STL.

Their implementation seems unnecessary complicated (check the sources here and here) but the main idea is to encapsulate the type that goes into the std::vector with a thin wrapper:

#include <vector>

template <typename T>
struct wrapper : public T
{
    wrapper() {}
    wrapper(const T& rhs) : T(rhs) {}
};

struct __declspec(align(64)) S
{
    float x, y, z, w;
};

int main()
{
    std::vector< wrapper<S> > v;  // OK, no C2719 error
    return 0;
}

About the implementation in Eigen, I must admit I don't quite understand

  • why they need Eigen::aligned_allocator_indirection,
  • why they need to make an exception for arithmetic types in EIGEN_WORKAROUND_MSVC_STL_SUPPORT,
  • why they need to define all these constructors and operators in Eigen::workaround_msvc_stl_support,
  • or why they need to redefine resize in their partial specialization of std::vector for the Eigen::aligned_allocator_indirection allocator...

Clues welcome. The point is, this trick works perfectly (as far as I can tell) and I don't see anything wrong with it, apart maybe from the slight inelegance.

like image 155
François Beaune Avatar answered Oct 04 '22 06:10

François Beaune