[eigen] about std::vector::resize (again)

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


Hi list,

as some of you know, and as a user remind us on the forum, we have not
finished yet the support for std::vector.

Indeed, the problem still occurs for custom classes having fixed size
Eigen objects:

struct A {
  Vector4f x;
  Matrix4f m;
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

std::vector<A,aligned_allocator> will fail because of bugged
vector<T>::resize(size_t,T). Our current solution is OK for Eigen's
types for which we workaround via several tricks. However this
solution is not extensible to user types (have to add special
constructor to discard the assertion, the specializations of
std::vector cannot be automatically generated by a macro, etc..).

So here is what I propose: let's be ugly !


#if define(_GLIBCXX_VECTOR) || define(_VECTOR_)
#error you must include Eigen/StdVector before std::vector
#endif

#define vector std_vector
#include <vector>
#undef vector

// now std::vector is actually reachable as std::std_vector !

namespace std {

// let's define our own std::vector inheriting the initial std::std_vector
template<typename T, typename AllocT = Eigen::aligned_allocator<T> >
class vector : public std::std_vector<T,AllocT>
{
    typedef std::std_vector<T,AllocT> Base;
  public:
    vector() : Base() {}
    vector(size_t s) : Base(s) {}
    vector(size_t s, const T& v) : Base(s,v) {}
    vector(const vector& v) : Base(v) {}
    vector& operator=(const vector& v) { Base::operator=(v); return *this; }

    void resize(size_type __new_size)
    { resize(__new_size, T()); }

    #if defined(_GLIBCXX_VECTOR)
    void resize(size_type __new_size, const T& __x)
    {
      if (__new_size < size())
        Base::_M_erase_at_end(this->_M_impl._M_start + __new_size);
      else
        Base::insert(Base::end(), __new_size - Base::size(), __x);
    }
    #elif defined(_VECTOR_)
    // workaround MSVC's vector
    void resize(size_type _Newsize, const T& _Val)
    {
      if (Base::size() < _Newsize)
        Base::_Insert_n(Base::end(), _Newsize - Base::size(), _Val);
      else if (_Newsize < Base::size())
        Base::erase(Base::begin() + _Newsize, Base::end());
    }
    #endif
};

}


yes I know this a bit ugly, but I don't know better solution to tackle
this issue once for all. Of course this is just a starting point. If
that really works, the next step is to have a specialization of
std::vector for classes having EIGEN_MAKE_ALIGNED_OPERATOR_NEW (this
is easy to detect), and do the workaround + "aligned_allocator as
default" only in this specialization.

I'll test it with MSVC tonight, and let you know.

cheers,
Gael.



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/