diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee134df06f18f25f442ba0d35efe1ef84d78d461..8ae903e993f537a699d830929198f7b175e0a680 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,12 +70,12 @@ ADD_REQUIRED_DEPENDENCY("eigen3 >= 3.0.5")
 SET(BOOST_COMPONENTS python)
 SEARCH_FOR_BOOST()
 # Add Boost path to include directories.
-INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
 
 FINDPYTHON(2.7 EXACT REQUIRED)
-INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(SYSTEM ${PYTHON_INCLUDE_DIRS})
 FIND_NUMPY()
-INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(SYSTEM ${NUMPY_INCLUDE_DIRS})
 
 # ----------------------------------------------------
 # --- INCLUDE ----------------------------------------
@@ -103,6 +103,7 @@ SET(HEADERS
   registration.hpp
   angle-axis.hpp
   quaternion.hpp
+  ref.hpp
 )
 
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/include/eigenpy")
diff --git a/src/details.hpp b/src/details.hpp
index 949ed0c21e7369b86f1cbafc17305024990a9aeb..6fe8295d21b6b1109963cf1ef6d0dc217012300d 100644
--- a/src/details.hpp
+++ b/src/details.hpp
@@ -17,20 +17,13 @@
 #ifndef __eigenpy_details_hpp__
 #define __eigenpy_details_hpp__
 
-#include <boost/python.hpp>
-#include <Eigen/Core>
-
-#include <numpy/numpyconfig.h>
-#ifdef NPY_1_8_API_VERSION
-#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
-#endif
+#include "eigenpy/fwd.hpp"
 
 #include <numpy/arrayobject.h>
 #include <iostream>
 
 #include "eigenpy/eigenpy.hpp"
 #include "eigenpy/registration.hpp"
-#include "eigenpy/exception.hpp"
 #include "eigenpy/map.hpp"
 
 
@@ -58,7 +51,7 @@ namespace eigenpy
     { return make((PyObject*)pyArray,copy); }
     bp::object make(PyObject* pyObj, bool copy = false)
     {
-      boost::python::object m
+      bp::object m
       = pyMatrixType(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
       Py_INCREF(m.ptr());
       return m;
@@ -67,16 +60,50 @@ namespace eigenpy
   protected:
     PyMatrixType()
     {
-      pyModule = boost::python::import("numpy");
+      pyModule = bp::import("numpy");
       pyMatrixType = pyModule.attr("matrix");
     }
 
     bp::object pyMatrixType;
     bp::object pyModule;
   };
+  
+  template<typename MatType>
+  struct EigenObjectAllocator
+  {
+    typedef MatType Type;
+    
+    static void allocate(PyArrayObject * pyArray, void * storage)
+    {
+      typename MapNumpy<MatType>::EigenMap numpyMap = MapNumpy<MatType>::map(pyArray);
+      new(storage) MatType(numpyMap);
+    }
+    
+    static void convert(Type const & mat , PyArrayObject * pyArray)
+    {
+      MapNumpy<MatType>::map(pyArray) = mat;
+    }
+  };
+  
+  template<typename MatType>
+  struct EigenObjectAllocator< eigenpy::Ref<MatType> >
+  {
+    typedef eigenpy::Ref<MatType> Type;
+    
+    static void allocate(PyArrayObject * pyArray, void * storage)
+    {
+      typename MapNumpy<MatType>::EigenMap numpyMap = MapNumpy<MatType>::map(pyArray);
+      new(storage) Type(numpyMap);
+    }
+    
+    static void convert(Type const & mat , PyArrayObject * pyArray)
+    {
+      MapNumpy<MatType>::map(pyArray) = mat;
+    }
+  };
 
   /* --- TO PYTHON -------------------------------------------------------------- */
-  template< typename MatType,typename EquivalentEigenType >
+  template<typename MatType>
   struct EigenToPy
   {
     static PyObject* convert(MatType const& mat)
@@ -88,139 +115,128 @@ namespace eigenpy
 
       npy_intp shape[2] = { R,C };
       PyArrayObject* pyArray = (PyArrayObject*)
-	PyArray_SimpleNew(2, shape, NumpyEquivalentType<T>::type_code);
+      PyArray_SimpleNew(2, shape, NumpyEquivalentType<T>::type_code);
 
-      MapNumpy<EquivalentEigenType>::map(pyArray) = mat;
+      EigenObjectAllocator<MatType>::convert(mat,pyArray);
 
       return PyMatrixType::getInstance().make(pyArray).ptr();
     }
   };
   
   /* --- FROM PYTHON ------------------------------------------------------------ */
-  namespace bp = boost::python;
-
-  template<typename MatType, int ROWS,int COLS>
-  struct TraitsMatrixConstructor
-  {
-    static MatType & construct(void*storage,int /*r*/,int /*c*/)
-    {
-      return * new(storage) MatType();
-    }
-  };
 
   template<typename MatType>
-  struct TraitsMatrixConstructor<MatType,Eigen::Dynamic,Eigen::Dynamic>
-  {
-    static MatType & construct(void*storage,int r,int c)
-    {
-      return * new(storage) MatType(r,c);
-    }
-  };
-
-  template<typename MatType,int R>
-  struct TraitsMatrixConstructor<MatType,R,Eigen::Dynamic>
-  {
-    static MatType & construct(void*storage,int /*r*/,int c)
-    {
-      return * new(storage) MatType(R,c);
-    }
-  };
-
-  template<typename MatType,int C>
-  struct TraitsMatrixConstructor<MatType,Eigen::Dynamic,C>
-  {
-    static MatType & construct(void*storage,int r,int /*c*/)
-    {
-      return * new(storage) MatType(r,C);
-    }
-  };
-
-
-  template<typename MatType,typename EquivalentEigenType>
   struct EigenFromPy
   {
     EigenFromPy()
     {
       bp::converter::registry::push_back
-	(reinterpret_cast<void *(*)(_object *)>(&convertible),
-	 &construct,bp::type_id<MatType>());
+      (reinterpret_cast<void *(*)(_object *)>(&convertible),
+       &construct,bp::type_id<MatType>());
     }
- 
+    
     // Determine if obj_ptr can be converted in a Eigenvec
     static void* convertible(PyArrayObject* obj_ptr)
     {
-      typedef typename MatType::Scalar T;
-
-      if (!PyArray_Check(obj_ptr)) 
-	{
+      if (!PyArray_Check(obj_ptr))
+      {
 #ifndef NDEBUG
-	  std::cerr << "The python object is not a numpy array." << std::endl;
+        std::cerr << "The python object is not a numpy array." << std::endl;
 #endif
-	  return 0;
-	}
-
+        return 0;
+      }
+      
+      if(MatType::IsVectorAtCompileTime)
+      {
+        if(PyArray_DIMS(obj_ptr)[0] > 1 && PyArray_DIMS(obj_ptr)[1] > 1)
+        {
+#ifndef NDEBUG
+          std::cerr << "The number of dimension of the object does not correspond to a vector" << std::endl;
+#endif
+          return 0;
+        }
+        
+        if(((PyArray_DIMS(obj_ptr)[0] == 1) && (MatType::ColsAtCompileTime == 1))
+           || ((PyArray_DIMS(obj_ptr)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
+        {
+#ifndef NDEBUG
+          if(MatType::ColsAtCompileTime == 1)
+            std::cerr << "The object is not a column vector" << std::endl;
+          else
+            std::cerr << "The object is not a row vector" << std::endl;
+#endif
+          return 0;
+        }
+      }
+      
       if (PyArray_NDIM(obj_ptr) != 2)
-	if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) )
-	  {
+      {
+        if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) )
+        {
 #ifndef NDEBUG
-	    std::cerr << "The number of dimension of the object is not correct." << std::endl;
+          std::cerr << "The number of dimension of the object is not correct." << std::endl;
 #endif
-	    return 0;
-	  }
-
-      if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) != NumpyEquivalentType<T>::type_code)
-	{
+          return 0;
+        }
+      }
+      
+      if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0))
+          != NumpyEquivalentType<typename MatType::Scalar>::type_code)
+      {
 #ifndef NDEBUG
-	  std::cerr << "The internal type as no Eigen equivalent." << std::endl;
+        std::cerr << "The internal type as no Eigen equivalent." << std::endl;
 #endif
-	  return 0;
-	}
+        return 0;
+      }
 #ifdef NPY_1_8_API_VERSION
       if (!(PyArray_FLAGS(obj_ptr)))
 #else
-      if (!(PyArray_FLAGS(obj_ptr) & NPY_ALIGNED))
+        if (!(PyArray_FLAGS(obj_ptr) & NPY_ALIGNED))
 #endif
-	{
+        {
 #ifndef NDEBUG
-	  std::cerr << "NPY non-aligned matrices are not implemented." << std::endl;
+          std::cerr << "NPY non-aligned matrices are not implemented." << std::endl;
 #endif
-	  return 0;
-	}
+          return 0;
+        }
       
       return obj_ptr;
     }
  
     // Convert obj_ptr into a Eigenvec
     static void construct(PyObject* pyObj,
-			  bp::converter::rvalue_from_python_stage1_data* memory)
+                          bp::converter::rvalue_from_python_stage1_data* memory)
     {
       using namespace Eigen;
-
+      
       PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
-      typename MapNumpy<EquivalentEigenType>::EigenMap numpyMap = MapNumpy<EquivalentEigenType>::map(pyArray);
-
+      assert((PyArray_DIMS(pyArray)[0]<INT_MAX) && (PyArray_DIMS(pyArray)[1]<INT_MAX));
+      
       void* storage = ((bp::converter::rvalue_from_python_storage<MatType>*)
-		       ((void*)memory))->storage.bytes;
-      assert( (numpyMap.rows()<INT_MAX) && (numpyMap.cols()<INT_MAX) 
-	      && "Map range larger than int ... can never happen." );
-      int r=(int)numpyMap.rows(),c=(int)numpyMap.cols();
-      EquivalentEigenType & eigenMatrix = //* new(storage) MatType(numpyMap.rows(),numpyMap.cols());
-	TraitsMatrixConstructor<MatType,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime>::construct (storage,r,c);
-      memory->convertible = storage;
+                       ((void*)memory))->storage.bytes;
+      
+      EigenObjectAllocator<MatType>::allocate(pyArray,storage);
 
-      eigenMatrix = numpyMap;
+      memory->convertible = storage;
     }
   };
+  
 #define numpy_import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); } }
   
   template<typename MatType,typename EigenEquivalentType>
   void enableEigenPySpecific()
+  {
+    enableEigenPySpecific<MatType>();
+  }
+  
+  template<typename MatType>
+  void enableEigenPySpecific()
   {
     numpy_import_array();
     if(check_registration<MatType>()) return;
     
-    boost::python::to_python_converter<MatType,EigenToPy<MatType,MatType> >();
-    EigenFromPy<MatType,MatType>();
+    bp::to_python_converter<MatType,EigenToPy<MatType> >();
+    EigenFromPy<MatType>();
   }
 
 } // namespace eigenpy
diff --git a/src/eigenpy.cpp b/src/eigenpy.cpp
index d0b685eb1490be7e423521f7a40dba068279f701..dae15e9d21fc932f12b4e867b16006cfe06dd9c9 100644
--- a/src/eigenpy.cpp
+++ b/src/eigenpy.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 LAAS-CNRS
+ * Copyright (c) 2015-2018 LAAS-CNRS
  *
  * This file is part of eigenpy.
  * eigenpy is free software: you can redistribute it and/or
@@ -22,17 +22,18 @@ namespace eigenpy
   /* Enable Eigen-Numpy serialization for a set of standard MatrixBase instance. */
   void enableEigenPy()
   {
+    using namespace Eigen;
     Exception::registerException();
 
-    enableEigenPySpecific<Eigen::MatrixXd,Eigen::MatrixXd>();
-    enableEigenPySpecific<Eigen::Matrix2d,Eigen::Matrix2d>();
-    enableEigenPySpecific<Eigen::Matrix3d,Eigen::Matrix3d>();
-    enableEigenPySpecific<Eigen::Matrix4d,Eigen::Matrix4d>();
-
-    enableEigenPySpecific<Eigen::VectorXd,Eigen::VectorXd>();
-    enableEigenPySpecific<Eigen::Vector2d,Eigen::Vector2d>();
-    enableEigenPySpecific<Eigen::Vector3d,Eigen::Vector3d>();
-    enableEigenPySpecific<Eigen::Vector4d,Eigen::Vector4d>();
+    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXd);
+    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2d);
+    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3d);
+    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4d);
+    
+    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXd);
+    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2d);
+    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3d);
+    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4d);
   }
 
 } // namespace eigenpy
diff --git a/src/eigenpy.hpp b/src/eigenpy.hpp
index cd01d8bcc6c44ca5aaa03304802ae55c8ecc573d..9fcecc7ce29815f09f02791c2228e889ee26e886 100644
--- a/src/eigenpy.hpp
+++ b/src/eigenpy.hpp
@@ -18,18 +18,27 @@
 #define __eigenpy_eigenpy_hpp__
 
 #include "eigenpy/fwd.hpp"
-#include "eigenpy/memory.hpp"
+#include "eigenpy/deprecated.hh"
+#include "eigenpy/ref.hpp"
+
+#define ENABLE_SPECIFIC_MATRIX_TYPE(TYPE) \
+  enableEigenPySpecific<TYPE>(); \
+  enableEigenPySpecific< eigenpy::Ref<TYPE> >();
 
 namespace eigenpy
 {
   /* Enable Eigen-Numpy serialization for a set of standard MatrixBase instance. */
   void enableEigenPy();
 
+  template<typename MatType>
+  void enableEigenPySpecific();
+  
   /* Enable the Eigen--Numpy serialization for the templated MatrixBase class.
    * The second template argument is used for inheritance of Eigen classes. If
    * using a native Eigen::MatrixBase, simply repeat the same arg twice. */
   template<typename MatType,typename EigenEquivalentType>
-  void enableEigenPySpecific();
+  EIGENPY_DEPRECATED void enableEigenPySpecific();
+
 
 } // namespace eigenpy
 
diff --git a/src/fwd.hpp b/src/fwd.hpp
index ab9cf717f2c6d2a5f3f87f5c422c6c0fcd88d4ba..d5d1f2e66ab8acb55b36771a1c0c3b989fced430 100644
--- a/src/fwd.hpp
+++ b/src/fwd.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2017, Nicolas Mansard and Justin Carpentier, LAAS-CNRS
+ * Copyright 2014-2018, Nicolas Mansard and Justin Carpentier, LAAS-CNRS
  *
  * This file is part of eigenpy.
  * eigenpy is free software: you can redistribute it and/or
@@ -20,8 +20,17 @@
 #include <boost/python.hpp>
 #include <Eigen/Core>
 
+#include <numpy/numpyconfig.h>
 #ifdef NPY_1_8_API_VERSION
 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
 #endif
 
+#include <numpy/noprefix.h>
+
+#ifdef NPY_ALIGNED
+#define EIGENPY_DEFAULT_ALIGNMENT_VALUE Eigen::Aligned16
+#else
+#define EIGENPY_DEFAULT_ALIGNMENT_VALUE Eigen::Unaligned
+#endif
+
 #endif // ifndef __eigenpy_fwd_hpp__
diff --git a/src/map.hpp b/src/map.hpp
index 0c0b633d48d3b181957bd165ec91ff44426f428a..2a2fb4b27f72126db743c4e1ee94756125857660 100644
--- a/src/map.hpp
+++ b/src/map.hpp
@@ -14,10 +14,9 @@
  * with eigenpy.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <boost/python.hpp>
-#include <Eigen/Core>
+#include "eigenpy/fwd.hpp"
 #include <numpy/arrayobject.h>
-#include <eigenpy/exception.hpp>
+#include "eigenpy/exception.hpp"
 
 namespace eigenpy
 {
@@ -30,6 +29,7 @@ namespace eigenpy
   {
     typedef MapNumpyTraits<MatType, MatType::IsVectorAtCompileTime> Impl;
     typedef typename Impl::EigenMap EigenMap;
+    typedef typename Impl::Stride Stride;
 
     static inline EigenMap map( PyArrayObject* pyArray );
    };
@@ -45,9 +45,9 @@ namespace eigenpy
   template<typename MatType>
   struct MapNumpyTraits<MatType,0>
   {
-    typedef Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic> Stride;
-    typedef Eigen::Map<MatType,0,Stride> EigenMap;
-    typedef typename MatType::Scalar T;
+    typedef typename StrideType<MatType>::type Stride;
+    typedef Eigen::Map<MatType,EIGENPY_DEFAULT_ALIGNMENT_VALUE,Stride> EigenMap;
+    typedef typename MatType::Scalar Scalar;
 
     static EigenMap mapImpl( PyArrayObject* pyArray )
     {
@@ -63,6 +63,9 @@ namespace eigenpy
       const long int itemsize = PyArray_ITEMSIZE(pyArray);
       const int stride1 = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
       const int stride2 = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
+      Stride stride(stride2,stride1);
+      
+      
       
       if( (MatType::RowsAtCompileTime!=R)
 	  && (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
@@ -71,17 +74,18 @@ namespace eigenpy
 	  && (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
 	{  throw eigenpy::Exception("The number of columns does not fit with the matrix type."); }
 
-      T* pyData = reinterpret_cast<T*>(PyArray_DATA(pyArray));
-      return EigenMap( pyData, R,C, Stride(stride2,stride1) );
+      Scalar* pyData = reinterpret_cast<Scalar*>(PyArray_DATA(pyArray));
+      
+      return EigenMap( pyData, R,C, stride );
     }
   };
 
   template<typename MatType>
   struct MapNumpyTraits<MatType,1>
   {
-    typedef Eigen::InnerStride<Eigen::Dynamic> Stride;
-    typedef Eigen::Map<MatType,0,Stride> EigenMap;
-    typedef typename MatType::Scalar T;
+    typedef typename StrideType<MatType>::type Stride;
+    typedef Eigen::Map<MatType,EIGENPY_DEFAULT_ALIGNMENT_VALUE,Stride> EigenMap;
+    typedef typename MatType::Scalar Scalar;
  
     static EigenMap mapImpl( PyArrayObject* pyArray )
     {
@@ -101,8 +105,8 @@ namespace eigenpy
 	      && (MatType::MaxSizeAtCompileTime!=Eigen::Dynamic) )
 	{ throw eigenpy::Exception("The number of elements does not fit with the vector type."); }
 
-      T* pyData = reinterpret_cast<T*>(PyArray_DATA(pyArray));
-      return EigenMap( pyData, R, 1, Stride(stride) );
+      Scalar* pyData = reinterpret_cast<Scalar*>(PyArray_DATA(pyArray));
+      return EigenMap( pyData, R, Stride(stride) );
     }
   };
 
diff --git a/src/memory.hpp b/src/memory.hpp
index 6a0b5f26fa4e6b98b423b9a83ae6096dc1af6a12..e63d5f425026d6f777af452cb1cb76b189cb52b1 100644
--- a/src/memory.hpp
+++ b/src/memory.hpp
@@ -79,7 +79,7 @@ namespace boost { namespace python { namespace objects { \
              \
             Py_ssize_t holder_offset = reinterpret_cast<Py_ssize_t>(holder) \
             - reinterpret_cast<Py_ssize_t>(&instance->storage) \
-            + offsetof(instance_t, storage); \
+            + static_cast<Py_ssize_t>(offsetof(instance_t, storage)); \
             Py_SIZE(instance) = holder_offset; \
              \
             protect.cancel(); \
diff --git a/src/ref.hpp b/src/ref.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..641228e1862ac20c3bec6225fe0b2169f7db6df8
--- /dev/null
+++ b/src/ref.hpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2018, Justin Carpentier <jcarpent@laas.fr>, LAAS-CNRS
+ *
+ * This file is part of eigenpy.
+ * eigenpy is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ * eigenpy is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.  You should
+ * have received a copy of the GNU Lesser General Public License along
+ * with eigenpy.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __eigenpy_ref_hpp__
+#define __eigenpy_ref_hpp__
+
+#include "eigenpy/fwd.hpp"
+
+// For old Eigen versions, EIGEN_DEVICE_FUNC is not defined.
+// We must define it just in the scope of this file.
+#if not EIGEN_VERSION_AT_LEAST(3,2,91)
+#define EIGEN_DEVICE_FUNC
+#endif
+
+namespace eigenpy
+{
+  template<typename MatType, int IsVectorAtCompileTime = MatType::IsVectorAtCompileTime>
+  struct StrideType
+  {
+    typedef Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic> type;
+  };
+  
+  template<typename MatType>
+  struct StrideType<MatType,1>
+  {
+    typedef Eigen::InnerStride<Eigen::Dynamic> type;
+  };
+  
+  template<typename PlainObjectType>
+  struct Ref : Eigen::Ref<PlainObjectType,EIGENPY_DEFAULT_ALIGNMENT_VALUE,typename StrideType<PlainObjectType>::type>
+  {
+  public:
+    typedef Eigen::Ref<PlainObjectType,EIGENPY_DEFAULT_ALIGNMENT_VALUE,typename StrideType<PlainObjectType>::type> Base;
+    
+  private:
+    typedef Eigen::internal::traits<Base> Traits;
+    template<typename Derived>
+    EIGEN_DEVICE_FUNC inline Ref(const Eigen::PlainObjectBase<Derived>& expr,
+                                 typename Eigen::internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0);
+    
+  public:
+    
+    typedef typename Eigen::internal::traits<Base>::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex<float>. */ \
+    typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex<T>, T were corresponding to RealScalar. */ \
+    typedef typename Base::CoeffReturnType CoeffReturnType; /*!< \brief The return type for coefficient access. \details Depending on whether the object allows direct coefficient access (e.g. for a MatrixXd), this type is either 'const Scalar&' or simply 'Scalar' for objects that do not allow direct coefficient access. */
+    typedef typename Eigen::internal::ref_selector<Base>::type Nested;
+    typedef typename Eigen::internal::traits<Base>::StorageKind StorageKind;
+#if EIGEN_VERSION_AT_LEAST(3,2,91)
+    typedef typename Eigen::internal::traits<Base>::StorageIndex StorageIndex;
+#else
+    typedef typename Eigen::internal::traits<Base>::Index StorageIndex;
+#endif
+    enum { RowsAtCompileTime = Eigen::internal::traits<Base>::RowsAtCompileTime,
+      ColsAtCompileTime = Eigen::internal::traits<Base>::ColsAtCompileTime,
+      Flags = Eigen::internal::traits<Base>::Flags,
+      SizeAtCompileTime = Base::SizeAtCompileTime,
+      MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime,
+      IsVectorAtCompileTime = Base::IsVectorAtCompileTime };
+    using Base::derived;
+    using Base::const_cast_derived;
+    typedef typename Base::PacketScalar PacketScalar;
+    
+    template<typename Derived>
+    EIGEN_DEVICE_FUNC inline Ref(Eigen::PlainObjectBase<Derived>& expr,
+                                 typename Eigen::internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
+    : Base(expr.derived())
+    {}
+    
+    template<typename Derived>
+    EIGEN_DEVICE_FUNC inline Ref(const Eigen::DenseBase<Derived>& expr,
+                                 typename Eigen::internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
+    : Base(expr.derived())
+    {}
+    
+#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 ||  defined(__CUDACC_VER__)) // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324)
+    using Base::operator =;
+#elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
+    using Base::operator =; \
+    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Ref& operator=(const Ref& other) { Base::operator=(other); return *this; } \
+    template <typename OtherDerived> \
+    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Ref& operator=(const Eigen::DenseBase<OtherDerived>& other) { Base::operator=(other.derived()); return *this; }
+#else
+    using Base::operator =; \
+    EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Ref& operator=(const Ref& other) \
+    { \
+      Base::operator=(other); \
+      return *this; \
+    }
+#endif
+    
+  }; // struct Ref<PlainObjectType>
+}
+
+#if not EIGEN_VERSION_AT_LEAST(3,2,91)
+#undef EIGEN_DEVICE_FUNC
+#endif
+
+#endif // ifndef __eigenpy_ref_hpp__
diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt
index 8524a1d62587be5d9d413913fc6911fb42f3ce70..8b0a15c8e797fe03b9f4e25cf95299208dd87603 100644
--- a/unittest/CMakeLists.txt
+++ b/unittest/CMakeLists.txt
@@ -1,5 +1,5 @@
 # 
-# Copyright (c) 2016 CNRS
+# Copyright (c) 2016-2018 CNRS
 # 
 # This file is part of eigenpy
 # eigenpy is free software: you can redistribute it
@@ -40,4 +40,5 @@ ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND})
 
 ADD_LIB_UNIT_TEST(matrix "eigen3")
 ADD_LIB_UNIT_TEST(geometry "eigen3")
+ADD_LIB_UNIT_TEST(ref "eigen3")
 
diff --git a/unittest/ref.cpp b/unittest/ref.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ca38fc059f7d987adbf1271d5a71b71afce1d0d
--- /dev/null
+++ b/unittest/ref.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018, Justin Carpentier <jcarpent@laas.fr>, LAAS-CNRS
+ *
+ * This file is part of eigenpy.
+ * eigenpy is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ * eigenpy is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.  You should
+ * have received a copy of the GNU Lesser General Public License along
+ * with eigenpy.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "eigenpy/eigenpy.hpp"
+#include <iostream>
+
+using namespace Eigen;
+using namespace eigenpy;
+
+template<typename MatType>
+void printMatrix(const eigenpy::Ref<MatType> & mat)
+{
+  if(MatType::IsVectorAtCompileTime)
+    std::cout << "isVector" << std::endl;
+  std::cout << "size: cols " << mat.cols() << " rows " << mat.rows() << std::endl;
+  std::cout << mat << std::endl;
+}
+
+template<typename MatType>
+void printVector(const eigenpy::Ref<MatType> & mat)
+{
+  EIGEN_STATIC_ASSERT_VECTOR_ONLY(MatType);
+  printMatrix(mat);
+}
+
+template<typename MatType>
+void setOnes(eigenpy::Ref<MatType> mat)
+{
+  mat.setOnes();
+}
+
+BOOST_PYTHON_MODULE(ref)
+{
+  namespace bp = boost::python;
+  eigenpy::enableEigenPy();
+  
+  bp::def("printMatrix", printMatrix<Vector3d>);
+  bp::def("printMatrix", printMatrix<VectorXd>);
+  bp::def("printMatrix", printMatrix<MatrixXd>);
+  
+  bp::def("printVector", printVector<VectorXd>);
+
+  bp::def("setOnes", setOnes<Vector3d>);
+  bp::def("setOnes", setOnes<VectorXd>);
+  bp::def("setOnes", setOnes<MatrixXd>);
+}