LCOV - code coverage report
Current view: top level - Core - Ref.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 52 60 86.7 %
Date: 1980-01-01 00:00:00 Functions: 24 30 80.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // This file is part of Eigen, a lightweight C++ template library
       2                 :            : // for linear algebra.
       3                 :            : //
       4                 :            : // Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
       5                 :            : //
       6                 :            : // This Source Code Form is subject to the terms of the Mozilla
       7                 :            : // Public License v. 2.0. If a copy of the MPL was not distributed
       8                 :            : // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
       9                 :            : 
      10                 :            : #ifndef EIGEN_REF_H
      11                 :            : #define EIGEN_REF_H
      12                 :            : 
      13                 :            : namespace Eigen {
      14                 :            : 
      15                 :            : namespace internal {
      16                 :            : 
      17                 :            : template<typename _PlainObjectType, int _Options, typename _StrideType>
      18                 :            : struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
      19                 :            :   : public traits<Map<_PlainObjectType, _Options, _StrideType> >
      20                 :            : {
      21                 :            :   typedef _PlainObjectType PlainObjectType;
      22                 :            :   typedef _StrideType StrideType;
      23                 :            :   enum {
      24                 :            :     Options = _Options,
      25                 :            :     Flags = traits<Map<_PlainObjectType, _Options, _StrideType> >::Flags | NestByRefBit,
      26                 :            :     Alignment = traits<Map<_PlainObjectType, _Options, _StrideType> >::Alignment
      27                 :            :   };
      28                 :            : 
      29                 :            :   template<typename Derived> struct match {
      30                 :            :     enum {
      31                 :            :       IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime,
      32                 :            :       HasDirectAccess = internal::has_direct_access<Derived>::ret,
      33                 :            :       StorageOrderMatch = IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
      34                 :            :       InnerStrideMatch = int(StrideType::InnerStrideAtCompileTime)==int(Dynamic)
      35                 :            :                       || int(StrideType::InnerStrideAtCompileTime)==int(Derived::InnerStrideAtCompileTime)
      36                 :            :                       || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
      37                 :            :       OuterStrideMatch = IsVectorAtCompileTime
      38                 :            :                       || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
      39                 :            :       // NOTE, this indirection of evaluator<Derived>::Alignment is needed
      40                 :            :       // to workaround a very strange bug in MSVC related to the instantiation
      41                 :            :       // of has_*ary_operator in evaluator<CwiseNullaryOp>.
      42                 :            :       // This line is surprisingly very sensitive. For instance, simply adding parenthesis
      43                 :            :       // as "DerivedAlignment = (int(evaluator<Derived>::Alignment))," will make MSVC fail...
      44                 :            :       DerivedAlignment = int(evaluator<Derived>::Alignment),
      45                 :            :       AlignmentMatch = (int(traits<PlainObjectType>::Alignment)==int(Unaligned)) || (DerivedAlignment >= int(Alignment)), // FIXME the first condition is not very clear, it should be replaced by the required alignment
      46                 :            :       ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
      47                 :            :       MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
      48                 :            :     };
      49                 :            :     typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
      50                 :            :   };
      51                 :            : 
      52                 :            : };
      53                 :            : 
      54                 :            : template<typename Derived>
      55                 :            : struct traits<RefBase<Derived> > : public traits<Derived> {};
      56                 :            : 
      57                 :            : }
      58                 :            : 
      59                 :            : template<typename Derived> class RefBase
      60                 :            :  : public MapBase<Derived>
      61                 :            : {
      62                 :            :   typedef typename internal::traits<Derived>::PlainObjectType PlainObjectType;
      63                 :            :   typedef typename internal::traits<Derived>::StrideType StrideType;
      64                 :            : 
      65                 :            : public:
      66                 :            : 
      67                 :            :   typedef MapBase<Derived> Base;
      68                 :            :   EIGEN_DENSE_PUBLIC_INTERFACE(RefBase)
      69                 :            : 
      70                 :          4 :   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const
      71                 :            :   {
      72                 :          4 :     return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
      73                 :            :   }
      74                 :            : 
      75                 :          4 :   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const
      76                 :            :   {
      77                 :          4 :     return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
      78                 :            :          : IsVectorAtCompileTime ? this->size()
      79                 :            :          : int(Flags)&RowMajorBit ? this->cols()
      80                 :          4 :          : this->rows();
      81                 :            :   }
      82                 :            : 
      83                 :          4 :   EIGEN_DEVICE_FUNC RefBase()
      84                 :            :     : Base(0,RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime),
      85                 :            :       // Stride<> does not allow default ctor for Dynamic strides, so let' initialize it with dummy values:
      86                 :          4 :       m_stride(StrideType::OuterStrideAtCompileTime==Dynamic?0:StrideType::OuterStrideAtCompileTime,
      87                 :          4 :                StrideType::InnerStrideAtCompileTime==Dynamic?0:StrideType::InnerStrideAtCompileTime)
      88                 :          4 :   {}
      89                 :            : 
      90                 :            :   EIGEN_INHERIT_ASSIGNMENT_OPERATORS(RefBase)
      91                 :            : 
      92                 :            : protected:
      93                 :            : 
      94                 :            :   typedef Stride<StrideType::OuterStrideAtCompileTime,StrideType::InnerStrideAtCompileTime> StrideBase;
      95                 :            : 
      96                 :            :   // Resolves inner stride if default 0.
      97                 :          8 :   static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveInnerStride(Index inner) {
      98                 :          8 :     return inner == 0 ? 1 : inner;
      99                 :            :   }
     100                 :            : 
     101                 :            :   // Resolves outer stride if default 0.
     102                 :          8 :   static EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index resolveOuterStride(Index inner, Index outer, Index rows, Index cols, bool isVectorAtCompileTime, bool isRowMajor) {
     103                 :          8 :     return outer == 0 ? isVectorAtCompileTime ? inner * rows * cols : isRowMajor ? inner * cols : inner * rows : outer;
     104                 :            :   }
     105                 :            : 
     106                 :            :   // Returns true if construction is valid, false if there is a stride mismatch,
     107                 :            :   // and fails if there is a size mismatch.
     108                 :            :   template<typename Expression>
     109                 :          4 :   EIGEN_DEVICE_FUNC bool construct(Expression& expr)
     110                 :            :   {
     111                 :            :     // Check matrix sizes.  If this is a compile-time vector, we do allow
     112                 :            :     // implicitly transposing.
     113                 :            :     EIGEN_STATIC_ASSERT(
     114                 :            :       EIGEN_PREDICATE_SAME_MATRIX_SIZE(PlainObjectType, Expression)
     115                 :            :       // If it is a vector, the transpose sizes might match.
     116                 :            :       || ( PlainObjectType::IsVectorAtCompileTime
     117                 :            :             && ((int(PlainObjectType::RowsAtCompileTime)==Eigen::Dynamic
     118                 :            :               || int(Expression::ColsAtCompileTime)==Eigen::Dynamic
     119                 :            :               || int(PlainObjectType::RowsAtCompileTime)==int(Expression::ColsAtCompileTime))
     120                 :            :             &&  (int(PlainObjectType::ColsAtCompileTime)==Eigen::Dynamic
     121                 :            :               || int(Expression::RowsAtCompileTime)==Eigen::Dynamic
     122                 :            :               || int(PlainObjectType::ColsAtCompileTime)==int(Expression::RowsAtCompileTime)))),
     123                 :            :       YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
     124                 :            :     )
     125                 :            : 
     126                 :            :     // Determine runtime rows and columns.
     127                 :          4 :     Index rows = expr.rows();
     128                 :          4 :     Index cols = expr.cols();
     129                 :            :     if(PlainObjectType::RowsAtCompileTime==1)
     130                 :            :     {
     131                 :            :       eigen_assert(expr.rows()==1 || expr.cols()==1);
     132                 :            :       rows = 1;
     133                 :            :       cols = expr.size();
     134                 :            :     }
     135                 :            :     else if(PlainObjectType::ColsAtCompileTime==1)
     136                 :            :     {
     137                 :          4 :       eigen_assert(expr.rows()==1 || expr.cols()==1);
     138                 :          4 :       rows = expr.size();
     139                 :          4 :       cols = 1;
     140                 :            :     }
     141                 :            :     // Verify that the sizes are valid.
     142                 :          4 :     eigen_assert(
     143                 :            :       (PlainObjectType::RowsAtCompileTime == Dynamic) || (PlainObjectType::RowsAtCompileTime == rows));
     144                 :          4 :     eigen_assert(
     145                 :            :       (PlainObjectType::ColsAtCompileTime == Dynamic) || (PlainObjectType::ColsAtCompileTime == cols));
     146                 :            : 
     147                 :            : 
     148                 :            :     // If this is a vector, we might be transposing, which means that stride should swap.
     149                 :          4 :     const bool transpose = PlainObjectType::IsVectorAtCompileTime && (rows != expr.rows());
     150                 :            :     // If the storage format differs, we also need to swap the stride.
     151                 :          4 :     const bool row_major = ((PlainObjectType::Flags)&RowMajorBit) != 0;
     152                 :          4 :     const bool expr_row_major = (Expression::Flags&RowMajorBit) != 0;
     153                 :          4 :     const bool storage_differs =  (row_major != expr_row_major);
     154                 :            : 
     155                 :          4 :     const bool swap_stride = (transpose != storage_differs);
     156                 :            : 
     157                 :            :     // Determine expr's actual strides, resolving any defaults if zero.
     158                 :          4 :     const Index expr_inner_actual = resolveInnerStride(expr.innerStride());
     159                 :          4 :     const Index expr_outer_actual = resolveOuterStride(expr_inner_actual,
     160                 :            :                                                        expr.outerStride(),
     161                 :            :                                                        expr.rows(),
     162                 :            :                                                        expr.cols(),
     163                 :            :                                                        Expression::IsVectorAtCompileTime != 0,
     164                 :            :                                                        expr_row_major);
     165                 :            : 
     166                 :            :     // If this is a column-major row vector or row-major column vector, the inner-stride
     167                 :            :     // is arbitrary, so set it to either the compile-time inner stride or 1.
     168                 :          4 :     const bool row_vector = (rows == 1);
     169                 :          4 :     const bool col_vector = (cols == 1);
     170                 :          4 :     const Index inner_stride =
     171                 :          8 :         ( (!row_major && row_vector) || (row_major && col_vector) ) ?
     172                 :            :             ( StrideType::InnerStrideAtCompileTime > 0 ? Index(StrideType::InnerStrideAtCompileTime) : 1)
     173                 :          4 :             : swap_stride ? expr_outer_actual : expr_inner_actual;
     174                 :            : 
     175                 :            :     // If this is a column-major column vector or row-major row vector, the outer-stride
     176                 :            :     // is arbitrary, so set it to either the compile-time outer stride or vector size.
     177                 :          4 :     const Index outer_stride =
     178                 :          4 :       ( (!row_major && col_vector) || (row_major && row_vector) ) ?
     179                 :          4 :           ( StrideType::OuterStrideAtCompileTime > 0 ? Index(StrideType::OuterStrideAtCompileTime) : rows * cols * inner_stride)
     180                 :          0 :           : swap_stride ? expr_inner_actual : expr_outer_actual;
     181                 :            : 
     182                 :            :     // Check if given inner/outer strides are compatible with compile-time strides.
     183                 :          4 :     const bool inner_valid = (StrideType::InnerStrideAtCompileTime == Dynamic)
     184                 :          4 :         || (resolveInnerStride(Index(StrideType::InnerStrideAtCompileTime)) == inner_stride);
     185                 :          4 :     if (!inner_valid) {
     186                 :          0 :       return false;
     187                 :            :     }
     188                 :            : 
     189                 :          4 :     const bool outer_valid = (StrideType::OuterStrideAtCompileTime == Dynamic)
     190                 :          4 :         || (resolveOuterStride(
     191                 :            :               inner_stride,
     192                 :            :               Index(StrideType::OuterStrideAtCompileTime),
     193                 :            :               rows, cols, PlainObjectType::IsVectorAtCompileTime != 0,
     194                 :            :               row_major)
     195                 :            :             == outer_stride);
     196                 :          4 :     if (!outer_valid) {
     197                 :          0 :       return false;
     198                 :            :     }
     199                 :            : 
     200                 :          4 :     ::new (static_cast<Base*>(this)) Base(expr.data(), rows, cols);
     201                 :          4 :     ::new (&m_stride) StrideBase(
     202                 :            :       (StrideType::OuterStrideAtCompileTime == 0) ? 0 : outer_stride,
     203                 :            :       (StrideType::InnerStrideAtCompileTime == 0) ? 0 : inner_stride );
     204                 :          4 :     return true;
     205                 :            :   }
     206                 :            : 
     207                 :            :   StrideBase m_stride;
     208                 :            : };
     209                 :            : 
     210                 :            : /** \class Ref
     211                 :            :   * \ingroup Core_Module
     212                 :            :   *
     213                 :            :   * \brief A matrix or vector expression mapping an existing expression
     214                 :            :   *
     215                 :            :   * \tparam PlainObjectType the equivalent matrix type of the mapped data
     216                 :            :   * \tparam Options specifies the pointer alignment in bytes. It can be: \c #Aligned128, , \c #Aligned64, \c #Aligned32, \c #Aligned16, \c #Aligned8 or \c #Unaligned.
     217                 :            :   *                 The default is \c #Unaligned.
     218                 :            :   * \tparam StrideType optionally specifies strides. By default, Ref implies a contiguous storage along the inner dimension (inner stride==1),
     219                 :            :   *                   but accepts a variable outer stride (leading dimension).
     220                 :            :   *                   This can be overridden by specifying strides.
     221                 :            :   *                   The type passed here must be a specialization of the Stride template, see examples below.
     222                 :            :   *
     223                 :            :   * This class provides a way to write non-template functions taking Eigen objects as parameters while limiting the number of copies.
     224                 :            :   * A Ref<> object can represent either a const expression or a l-value:
     225                 :            :   * \code
     226                 :            :   * // in-out argument:
     227                 :            :   * void foo1(Ref<VectorXf> x);
     228                 :            :   *
     229                 :            :   * // read-only const argument:
     230                 :            :   * void foo2(const Ref<const VectorXf>& x);
     231                 :            :   * \endcode
     232                 :            :   *
     233                 :            :   * In the in-out case, the input argument must satisfy the constraints of the actual Ref<> type, otherwise a compilation issue will be triggered.
     234                 :            :   * By default, a Ref<VectorXf> can reference any dense vector expression of float having a contiguous memory layout.
     235                 :            :   * Likewise, a Ref<MatrixXf> can reference any column-major dense matrix expression of float whose column's elements are contiguously stored with
     236                 :            :   * the possibility to have a constant space in-between each column, i.e. the inner stride must be equal to 1, but the outer stride (or leading dimension)
     237                 :            :   * can be greater than the number of rows.
     238                 :            :   *
     239                 :            :   * In the const case, if the input expression does not match the above requirement, then it is evaluated into a temporary before being passed to the function.
     240                 :            :   * Here are some examples:
     241                 :            :   * \code
     242                 :            :   * MatrixXf A;
     243                 :            :   * VectorXf a;
     244                 :            :   * foo1(a.head());             // OK
     245                 :            :   * foo1(A.col());              // OK
     246                 :            :   * foo1(A.row());              // Compilation error because here innerstride!=1
     247                 :            :   * foo2(A.row());              // Compilation error because A.row() is a 1xN object while foo2 is expecting a Nx1 object
     248                 :            :   * foo2(A.row().transpose());  // The row is copied into a contiguous temporary
     249                 :            :   * foo2(2*a);                  // The expression is evaluated into a temporary
     250                 :            :   * foo2(A.col().segment(2,4)); // No temporary
     251                 :            :   * \endcode
     252                 :            :   *
     253                 :            :   * The range of inputs that can be referenced without temporary can be enlarged using the last two template parameters.
     254                 :            :   * Here is an example accepting an innerstride!=1:
     255                 :            :   * \code
     256                 :            :   * // in-out argument:
     257                 :            :   * void foo3(Ref<VectorXf,0,InnerStride<> > x);
     258                 :            :   * foo3(A.row());              // OK
     259                 :            :   * \endcode
     260                 :            :   * The downside here is that the function foo3 might be significantly slower than foo1 because it won't be able to exploit vectorization, and will involve more
     261                 :            :   * expensive address computations even if the input is contiguously stored in memory. To overcome this issue, one might propose to overload internally calling a
     262                 :            :   * template function, e.g.:
     263                 :            :   * \code
     264                 :            :   * // in the .h:
     265                 :            :   * void foo(const Ref<MatrixXf>& A);
     266                 :            :   * void foo(const Ref<MatrixXf,0,Stride<> >& A);
     267                 :            :   *
     268                 :            :   * // in the .cpp:
     269                 :            :   * template<typename TypeOfA> void foo_impl(const TypeOfA& A) {
     270                 :            :   *     ... // crazy code goes here
     271                 :            :   * }
     272                 :            :   * void foo(const Ref<MatrixXf>& A) { foo_impl(A); }
     273                 :            :   * void foo(const Ref<MatrixXf,0,Stride<> >& A) { foo_impl(A); }
     274                 :            :   * \endcode
     275                 :            :   *
     276                 :            :   * See also the following stackoverflow questions for further references:
     277                 :            :   *  - <a href="http://stackoverflow.com/questions/21132538/correct-usage-of-the-eigenref-class">Correct usage of the Eigen::Ref<> class</a>
     278                 :            :   *
     279                 :            :   * \sa PlainObjectBase::Map(), \ref TopicStorageOrders
     280                 :            :   */
     281                 :            : template<typename PlainObjectType, int Options, typename StrideType> class Ref
     282                 :            :   : public RefBase<Ref<PlainObjectType, Options, StrideType> >
     283                 :            : {
     284                 :            :   private:
     285                 :            :     typedef internal::traits<Ref> Traits;
     286                 :            :     template<typename Derived>
     287                 :            :     EIGEN_DEVICE_FUNC inline Ref(const PlainObjectBase<Derived>& expr,
     288                 :            :                                  typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0);
     289                 :            :   public:
     290                 :            : 
     291                 :            :     typedef RefBase<Ref> Base;
     292                 :            :     EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
     293                 :            : 
     294                 :            : 
     295                 :            :     #ifndef EIGEN_PARSED_BY_DOXYGEN
     296                 :            :     template<typename Derived>
     297                 :            :     EIGEN_DEVICE_FUNC inline Ref(PlainObjectBase<Derived>& expr,
     298                 :            :                                  typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
     299                 :            :     {
     300                 :            :       EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
     301                 :            :       // Construction must pass since we will not create temprary storage in the non-const case.
     302                 :            :       const bool success = Base::construct(expr.derived());
     303                 :            :       EIGEN_UNUSED_VARIABLE(success)
     304                 :            :       eigen_assert(success);
     305                 :            :     }
     306                 :            :     template<typename Derived>
     307                 :            :     EIGEN_DEVICE_FUNC inline Ref(const DenseBase<Derived>& expr,
     308                 :            :                                  typename internal::enable_if<bool(Traits::template match<Derived>::MatchAtCompileTime),Derived>::type* = 0)
     309                 :            :     #else
     310                 :            :     /** Implicit constructor from any dense expression */
     311                 :            :     template<typename Derived>
     312                 :            :     inline Ref(DenseBase<Derived>& expr)
     313                 :            :     #endif
     314                 :            :     {
     315                 :            :       EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
     316                 :            :       EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
     317                 :            :       EIGEN_STATIC_ASSERT(!Derived::IsPlainObjectBase,THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
     318                 :            :       // Construction must pass since we will not create temporary storage in the non-const case.
     319                 :            :       const bool success = Base::construct(expr.const_cast_derived());
     320                 :            :       EIGEN_UNUSED_VARIABLE(success)
     321                 :            :       eigen_assert(success);
     322                 :            :     }
     323                 :            : 
     324                 :            :     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Ref)
     325                 :            : 
     326                 :            : };
     327                 :            : 
     328                 :            : // this is the const ref version
     329                 :            : template<typename TPlainObjectType, int Options, typename StrideType> class Ref<const TPlainObjectType, Options, StrideType>
     330                 :            :   : public RefBase<Ref<const TPlainObjectType, Options, StrideType> >
     331                 :            : {
     332                 :            :     typedef internal::traits<Ref> Traits;
     333                 :            :   public:
     334                 :            : 
     335                 :            :     typedef RefBase<Ref> Base;
     336                 :            :     EIGEN_DENSE_PUBLIC_INTERFACE(Ref)
     337                 :            : 
     338                 :            :     template<typename Derived>
     339                 :          4 :     EIGEN_DEVICE_FUNC inline Ref(const DenseBase<Derived>& expr,
     340                 :            :                                  typename internal::enable_if<bool(Traits::template match<Derived>::ScalarTypeMatch),Derived>::type* = 0)
     341                 :          4 :     {
     342                 :            : //      std::cout << match_helper<Derived>::HasDirectAccess << "," << match_helper<Derived>::OuterStrideMatch << "," << match_helper<Derived>::InnerStrideMatch << "\n";
     343                 :            : //      std::cout << int(StrideType::OuterStrideAtCompileTime) << " - " << int(Derived::OuterStrideAtCompileTime) << "\n";
     344                 :            : //      std::cout << int(StrideType::InnerStrideAtCompileTime) << " - " << int(Derived::InnerStrideAtCompileTime) << "\n";
     345                 :          4 :       construct(expr.derived(), typename Traits::template match<Derived>::type());
     346                 :          4 :     }
     347                 :            : 
     348                 :            :     EIGEN_DEVICE_FUNC inline Ref(const Ref& other) : Base(other) {
     349                 :            :       // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
     350                 :            :     }
     351                 :            : 
     352                 :            :     template<typename OtherRef>
     353                 :            :     EIGEN_DEVICE_FUNC inline Ref(const RefBase<OtherRef>& other) {
     354                 :            :       construct(other.derived(), typename Traits::template match<OtherRef>::type());
     355                 :            :     }
     356                 :            : 
     357                 :            :   protected:
     358                 :            : 
     359                 :            :     template<typename Expression>
     360                 :          4 :     EIGEN_DEVICE_FUNC void construct(const Expression& expr,internal::true_type)
     361                 :            :     {
     362                 :            :       // Check if we can use the underlying expr's storage directly, otherwise call the copy version.
     363                 :          4 :       if (!Base::construct(expr)) {
     364                 :          0 :         construct(expr, internal::false_type());
     365                 :            :       }
     366                 :          4 :     }
     367                 :            : 
     368                 :            :     template<typename Expression>
     369                 :          0 :     EIGEN_DEVICE_FUNC void construct(const Expression& expr, internal::false_type)
     370                 :            :     {
     371                 :          0 :       internal::call_assignment_no_alias(m_object,expr,internal::assign_op<Scalar,Scalar>());
     372                 :          0 :       Base::construct(m_object);
     373                 :          0 :     }
     374                 :            : 
     375                 :            :   protected:
     376                 :            :     TPlainObjectType m_object;
     377                 :            : };
     378                 :            : 
     379                 :            : } // end namespace Eigen
     380                 :            : 
     381                 :            : #endif // EIGEN_REF_H

Generated by: LCOV version 1.0