cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

stl_iterators.cpp (19411B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2018-2019 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 #include "main.h"
     11 #include <iterator>
     12 #include <numeric>
     13 
     14 template< class Iterator >
     15 std::reverse_iterator<Iterator>
     16 make_reverse_iterator( Iterator i )
     17 {
     18   return std::reverse_iterator<Iterator>(i);
     19 }
     20 
     21 #if !EIGEN_HAS_CXX11
     22 template<class ForwardIt>
     23 ForwardIt is_sorted_until(ForwardIt firstIt, ForwardIt lastIt)
     24 {
     25     if (firstIt != lastIt) {
     26         ForwardIt next = firstIt;
     27         while (++next != lastIt) {
     28             if (*next < *firstIt)
     29                 return next;
     30             firstIt = next;
     31         }
     32     }
     33     return lastIt;
     34 }
     35 template<class ForwardIt>
     36 bool is_sorted(ForwardIt firstIt, ForwardIt lastIt)
     37 {
     38     return ::is_sorted_until(firstIt, lastIt) == lastIt;
     39 }
     40 #else
     41 using std::is_sorted;
     42 #endif
     43 
     44 template<typename XprType>
     45 bool is_pointer_based_stl_iterator(const internal::pointer_based_stl_iterator<XprType> &) { return true; }
     46 
     47 template<typename XprType>
     48 bool is_generic_randaccess_stl_iterator(const internal::generic_randaccess_stl_iterator<XprType> &) { return true; }
     49 
     50 template<typename Iter>
     51 bool is_default_constructible_and_assignable(const Iter& it)
     52 {
     53 #if EIGEN_HAS_CXX11
     54   VERIFY(std::is_default_constructible<Iter>::value);
     55   VERIFY(std::is_nothrow_default_constructible<Iter>::value);
     56 #endif
     57   Iter it2;
     58   it2 = it;
     59   return (it==it2);
     60 }
     61 
     62 template<typename Xpr>
     63 void check_begin_end_for_loop(Xpr xpr)
     64 {
     65   const Xpr& cxpr(xpr);
     66   Index i = 0;
     67 
     68   i = 0;
     69   for(typename Xpr::iterator it = xpr.begin(); it!=xpr.end(); ++it) { VERIFY_IS_EQUAL(*it,xpr[i++]); }
     70 
     71   i = 0;
     72   for(typename Xpr::const_iterator it = xpr.cbegin(); it!=xpr.cend(); ++it) { VERIFY_IS_EQUAL(*it,xpr[i++]); }
     73 
     74   i = 0;
     75   for(typename Xpr::const_iterator it = cxpr.begin(); it!=cxpr.end(); ++it) { VERIFY_IS_EQUAL(*it,xpr[i++]); }
     76 
     77   i = 0;
     78   for(typename Xpr::const_iterator it = xpr.begin(); it!=xpr.end(); ++it) { VERIFY_IS_EQUAL(*it,xpr[i++]); }
     79 
     80   {
     81     // simple API check
     82     typename Xpr::const_iterator cit = xpr.begin();
     83     cit = xpr.cbegin();
     84 
     85     #if EIGEN_HAS_CXX11
     86     auto tmp1 = xpr.begin();
     87     VERIFY(tmp1==xpr.begin());
     88     auto tmp2 = xpr.cbegin();
     89     VERIFY(tmp2==xpr.cbegin());
     90     #endif
     91   }
     92 
     93   VERIFY( xpr.end() -xpr.begin()  == xpr.size() );
     94   VERIFY( xpr.cend()-xpr.begin()  == xpr.size() );
     95   VERIFY( xpr.end() -xpr.cbegin() == xpr.size() );
     96   VERIFY( xpr.cend()-xpr.cbegin() == xpr.size() );
     97 
     98   if(xpr.size()>0) {
     99     VERIFY(xpr.begin() != xpr.end());
    100     VERIFY(xpr.begin() < xpr.end());
    101     VERIFY(xpr.begin() <= xpr.end());
    102     VERIFY(!(xpr.begin() == xpr.end()));
    103     VERIFY(!(xpr.begin() > xpr.end()));
    104     VERIFY(!(xpr.begin() >= xpr.end()));
    105     
    106     VERIFY(xpr.cbegin() != xpr.end());
    107     VERIFY(xpr.cbegin() < xpr.end());
    108     VERIFY(xpr.cbegin() <= xpr.end());
    109     VERIFY(!(xpr.cbegin() == xpr.end()));
    110     VERIFY(!(xpr.cbegin() > xpr.end()));
    111     VERIFY(!(xpr.cbegin() >= xpr.end()));
    112 
    113     VERIFY(xpr.begin() != xpr.cend());
    114     VERIFY(xpr.begin() < xpr.cend());
    115     VERIFY(xpr.begin() <= xpr.cend());
    116     VERIFY(!(xpr.begin() == xpr.cend()));
    117     VERIFY(!(xpr.begin() > xpr.cend()));
    118     VERIFY(!(xpr.begin() >= xpr.cend()));
    119   }
    120 }
    121 
    122 template<typename Scalar, int Rows, int Cols>
    123 void test_stl_iterators(int rows=Rows, int cols=Cols)
    124 {
    125   typedef Matrix<Scalar,Rows,1> VectorType;
    126   #if EIGEN_HAS_CXX11
    127   typedef Matrix<Scalar,1,Cols> RowVectorType;
    128   #endif
    129   typedef Matrix<Scalar,Rows,Cols,ColMajor> ColMatrixType;
    130   typedef Matrix<Scalar,Rows,Cols,RowMajor> RowMatrixType;
    131   VectorType v = VectorType::Random(rows);
    132   const VectorType& cv(v);
    133   ColMatrixType A = ColMatrixType::Random(rows,cols);
    134   const ColMatrixType& cA(A);
    135   RowMatrixType B = RowMatrixType::Random(rows,cols);
    136   
    137   Index i, j;
    138 
    139   // Verify that iterators are default constructible (See bug #1900)
    140   {
    141     VERIFY( is_default_constructible_and_assignable(v.begin()));
    142     VERIFY( is_default_constructible_and_assignable(v.end()));
    143     VERIFY( is_default_constructible_and_assignable(cv.begin()));
    144     VERIFY( is_default_constructible_and_assignable(cv.end()));
    145 
    146     VERIFY( is_default_constructible_and_assignable(A.row(0).begin()));
    147     VERIFY( is_default_constructible_and_assignable(A.row(0).end()));
    148     VERIFY( is_default_constructible_and_assignable(cA.row(0).begin()));
    149     VERIFY( is_default_constructible_and_assignable(cA.row(0).end()));
    150 
    151     VERIFY( is_default_constructible_and_assignable(B.row(0).begin()));
    152     VERIFY( is_default_constructible_and_assignable(B.row(0).end()));
    153   }
    154 
    155   // Check we got a fast pointer-based iterator when expected
    156   {
    157     VERIFY( is_pointer_based_stl_iterator(v.begin()) );
    158     VERIFY( is_pointer_based_stl_iterator(v.end()) );
    159     VERIFY( is_pointer_based_stl_iterator(cv.begin()) );
    160     VERIFY( is_pointer_based_stl_iterator(cv.end()) );
    161 
    162     j = internal::random<Index>(0,A.cols()-1);
    163     VERIFY( is_pointer_based_stl_iterator(A.col(j).begin()) );
    164     VERIFY( is_pointer_based_stl_iterator(A.col(j).end()) );
    165     VERIFY( is_pointer_based_stl_iterator(cA.col(j).begin()) );
    166     VERIFY( is_pointer_based_stl_iterator(cA.col(j).end()) );
    167 
    168     i = internal::random<Index>(0,A.rows()-1);
    169     VERIFY( is_pointer_based_stl_iterator(A.row(i).begin()) );
    170     VERIFY( is_pointer_based_stl_iterator(A.row(i).end()) );
    171     VERIFY( is_pointer_based_stl_iterator(cA.row(i).begin()) );
    172     VERIFY( is_pointer_based_stl_iterator(cA.row(i).end()) );
    173 
    174     VERIFY( is_pointer_based_stl_iterator(A.reshaped().begin()) );
    175     VERIFY( is_pointer_based_stl_iterator(A.reshaped().end()) );
    176     VERIFY( is_pointer_based_stl_iterator(cA.reshaped().begin()) );
    177     VERIFY( is_pointer_based_stl_iterator(cA.reshaped().end()) );
    178 
    179     VERIFY( is_pointer_based_stl_iterator(B.template reshaped<AutoOrder>().begin()) );
    180     VERIFY( is_pointer_based_stl_iterator(B.template reshaped<AutoOrder>().end()) );
    181 
    182     VERIFY( is_generic_randaccess_stl_iterator(A.template reshaped<RowMajor>().begin()) );
    183     VERIFY( is_generic_randaccess_stl_iterator(A.template reshaped<RowMajor>().end()) );
    184   }
    185 
    186   {
    187     check_begin_end_for_loop(v);
    188     check_begin_end_for_loop(A.col(internal::random<Index>(0,A.cols()-1)));
    189     check_begin_end_for_loop(A.row(internal::random<Index>(0,A.rows()-1)));
    190     check_begin_end_for_loop(v+v);
    191   }
    192 
    193 #if EIGEN_HAS_CXX11
    194   // check swappable
    195   {
    196     using std::swap;
    197     // pointer-based
    198     {
    199       VectorType v_copy = v;
    200       auto a = v.begin();
    201       auto b = v.end()-1;
    202       swap(a,b);
    203       VERIFY_IS_EQUAL(v,v_copy);
    204       VERIFY_IS_EQUAL(*b,*v.begin());
    205       VERIFY_IS_EQUAL(*b,v(0));
    206       VERIFY_IS_EQUAL(*a,v.end()[-1]);
    207       VERIFY_IS_EQUAL(*a,v(last));
    208     }
    209 
    210     // generic
    211     {
    212       RowMatrixType B_copy = B;
    213       auto Br = B.reshaped();
    214       auto a = Br.begin();
    215       auto b = Br.end()-1;
    216       swap(a,b);
    217       VERIFY_IS_EQUAL(B,B_copy);
    218       VERIFY_IS_EQUAL(*b,*Br.begin());
    219       VERIFY_IS_EQUAL(*b,Br(0));
    220       VERIFY_IS_EQUAL(*a,Br.end()[-1]);
    221       VERIFY_IS_EQUAL(*a,Br(last));
    222     }
    223   }
    224 
    225   // check non-const iterator with for-range loops
    226   {
    227     i = 0;
    228     for(auto x : v) { VERIFY_IS_EQUAL(x,v[i++]); }
    229 
    230     j = internal::random<Index>(0,A.cols()-1);
    231     i = 0;
    232     for(auto x : A.col(j)) { VERIFY_IS_EQUAL(x,A(i++,j)); }
    233 
    234     i = 0;
    235     for(auto x : (v+A.col(j))) { VERIFY_IS_APPROX(x,v(i)+A(i,j)); ++i; }
    236 
    237     j = 0;
    238     i = internal::random<Index>(0,A.rows()-1);
    239     for(auto x : A.row(i)) { VERIFY_IS_EQUAL(x,A(i,j++)); }
    240 
    241     i = 0;
    242     for(auto x : A.reshaped()) { VERIFY_IS_EQUAL(x,A(i++)); }
    243   }
    244 
    245   // same for const_iterator
    246   {
    247     i = 0;
    248     for(auto x : cv) { VERIFY_IS_EQUAL(x,v[i++]); }
    249 
    250     i = 0;
    251     for(auto x : cA.reshaped()) { VERIFY_IS_EQUAL(x,A(i++)); }
    252 
    253     j = 0;
    254     i = internal::random<Index>(0,A.rows()-1);
    255     for(auto x : cA.row(i)) { VERIFY_IS_EQUAL(x,A(i,j++)); }
    256   }
    257 
    258   // check reshaped() on row-major
    259   {
    260     i = 0;
    261     Matrix<Scalar,Dynamic,Dynamic,ColMajor> Bc = B;
    262     for(auto x : B.reshaped()) { VERIFY_IS_EQUAL(x,Bc(i++)); }
    263   }
    264 
    265   // check write access
    266   {
    267     VectorType w(v.size());
    268     i = 0;
    269     for(auto& x : w) { x = v(i++); }
    270     VERIFY_IS_EQUAL(v,w);
    271   }
    272 
    273   // check for dangling pointers
    274   {
    275     // no dangling because pointer-based
    276     {
    277       j = internal::random<Index>(0,A.cols()-1);
    278       auto it = A.col(j).begin();
    279       for(i=0;i<rows;++i) {
    280         VERIFY_IS_EQUAL(it[i],A(i,j));
    281       }
    282     }
    283 
    284     // no dangling because pointer-based
    285     {
    286       i = internal::random<Index>(0,A.rows()-1);
    287       auto it = A.row(i).begin();
    288       for(j=0;j<cols;++j) { VERIFY_IS_EQUAL(it[j],A(i,j)); }
    289     }
    290 
    291     {
    292       j = internal::random<Index>(0,A.cols()-1);
    293       // this would produce a dangling pointer:
    294       // auto it = (A+2*A).col(j).begin(); 
    295       // we need to name the temporary expression:
    296       auto tmp = (A+2*A).col(j);
    297       auto it = tmp.begin();
    298       for(i=0;i<rows;++i) {
    299         VERIFY_IS_APPROX(it[i],3*A(i,j));
    300       }
    301     }
    302   }
    303 
    304   {
    305     // check basic for loop on vector-wise iterators
    306     j=0;
    307     for (auto it = A.colwise().cbegin(); it != A.colwise().cend(); ++it, ++j) {
    308       VERIFY_IS_APPROX( it->coeff(0), A(0,j) );
    309       VERIFY_IS_APPROX( (*it).coeff(0), A(0,j) );
    310     }
    311     j=0;
    312     for (auto it = A.colwise().begin(); it != A.colwise().end(); ++it, ++j) {
    313       (*it).coeffRef(0) = (*it).coeff(0); // compilation check
    314       it->coeffRef(0) = it->coeff(0);     // compilation check
    315       VERIFY_IS_APPROX( it->coeff(0), A(0,j) );
    316       VERIFY_IS_APPROX( (*it).coeff(0), A(0,j) );
    317     }
    318 
    319     // check valuetype gives us a copy
    320     j=0;
    321     for (auto it = A.colwise().cbegin(); it != A.colwise().cend(); ++it, ++j) {
    322       typename decltype(it)::value_type tmp = *it;
    323       VERIFY_IS_NOT_EQUAL( tmp.data() , it->data() );
    324       VERIFY_IS_APPROX( tmp, A.col(j) );
    325     }
    326   }
    327 
    328 #endif
    329 
    330   if(rows>=3) {
    331     VERIFY_IS_EQUAL((v.begin()+rows/2)[1], v(rows/2+1));
    332 
    333     VERIFY_IS_EQUAL((A.rowwise().begin()+rows/2)[1], A.row(rows/2+1));
    334   }
    335 
    336   if(cols>=3) {
    337     VERIFY_IS_EQUAL((A.colwise().begin()+cols/2)[1], A.col(cols/2+1));
    338   }
    339 
    340   // check std::sort
    341   {
    342     // first check that is_sorted returns false when required
    343     if(rows>=2)
    344     {
    345       v(1) = v(0)-Scalar(1);
    346       #if EIGEN_HAS_CXX11
    347       VERIFY(!is_sorted(std::begin(v),std::end(v)));
    348       #else
    349       VERIFY(!is_sorted(v.cbegin(),v.cend()));
    350       #endif
    351     }
    352 
    353     // on a vector
    354     {
    355       std::sort(v.begin(),v.end());
    356       VERIFY(is_sorted(v.begin(),v.end()));
    357       VERIFY(!::is_sorted(make_reverse_iterator(v.end()),make_reverse_iterator(v.begin())));
    358     }
    359 
    360     // on a column of a column-major matrix -> pointer-based iterator and default increment
    361     {
    362       j = internal::random<Index>(0,A.cols()-1);
    363       // std::sort(begin(A.col(j)),end(A.col(j))); // does not compile because this returns const iterators
    364       typename ColMatrixType::ColXpr Acol = A.col(j);
    365       std::sort(Acol.begin(),Acol.end());
    366       VERIFY(is_sorted(Acol.cbegin(),Acol.cend()));
    367       A.setRandom();
    368 
    369       std::sort(A.col(j).begin(),A.col(j).end());
    370       VERIFY(is_sorted(A.col(j).cbegin(),A.col(j).cend()));
    371       A.setRandom();
    372     }
    373 
    374     // on a row of a rowmajor matrix -> pointer-based iterator and runtime increment
    375     {
    376       i = internal::random<Index>(0,A.rows()-1);
    377       typename ColMatrixType::RowXpr Arow = A.row(i);
    378       VERIFY_IS_EQUAL( std::distance(Arow.begin(),Arow.end()), cols);
    379       std::sort(Arow.begin(),Arow.end());
    380       VERIFY(is_sorted(Arow.cbegin(),Arow.cend()));
    381       A.setRandom();
    382 
    383       std::sort(A.row(i).begin(),A.row(i).end());
    384       VERIFY(is_sorted(A.row(i).cbegin(),A.row(i).cend()));
    385       A.setRandom();
    386     }
    387 
    388     // with a generic iterator
    389     {
    390       Reshaped<RowMatrixType,RowMatrixType::SizeAtCompileTime,1> B1 = B.reshaped();
    391       std::sort(B1.begin(),B1.end());
    392       VERIFY(is_sorted(B1.cbegin(),B1.cend()));
    393       B.setRandom();
    394 
    395       // assertion because nested expressions are different
    396       // std::sort(B.reshaped().begin(),B.reshaped().end());
    397       // VERIFY(is_sorted(B.reshaped().cbegin(),B.reshaped().cend()));
    398       // B.setRandom();
    399     }
    400   }
    401 
    402   // check with partial_sum
    403   {
    404     j = internal::random<Index>(0,A.cols()-1);
    405     typename ColMatrixType::ColXpr Acol = A.col(j);
    406     std::partial_sum(Acol.begin(), Acol.end(), v.begin());
    407     VERIFY_IS_APPROX(v(seq(1,last)), v(seq(0,last-1))+Acol(seq(1,last)));
    408 
    409     // inplace
    410     std::partial_sum(Acol.begin(), Acol.end(), Acol.begin());
    411     VERIFY_IS_APPROX(v, Acol);
    412   }
    413 
    414   // stress random access as required by std::nth_element
    415   if(rows>=3)
    416   {
    417     v.setRandom();
    418     VectorType v1 = v;
    419     std::sort(v1.begin(),v1.end());
    420     std::nth_element(v.begin(), v.begin()+rows/2, v.end());
    421     VERIFY_IS_APPROX(v1(rows/2), v(rows/2));
    422 
    423     v.setRandom();
    424     v1 = v;
    425     std::sort(v1.begin()+rows/2,v1.end());
    426     std::nth_element(v.begin()+rows/2, v.begin()+rows/4, v.end());
    427     VERIFY_IS_APPROX(v1(rows/4), v(rows/4));
    428   }
    429 
    430 #if EIGEN_HAS_CXX11
    431   // check rows/cols iterators with range-for loops
    432   {
    433     j = 0;
    434     for(auto c : A.colwise()) { VERIFY_IS_APPROX(c.sum(), A.col(j).sum()); ++j; }
    435     j = 0;
    436     for(auto c : B.colwise()) { VERIFY_IS_APPROX(c.sum(), B.col(j).sum()); ++j; }
    437 
    438     j = 0;
    439     for(auto c : B.colwise()) {
    440       i = 0;
    441       for(auto& x : c) {
    442         VERIFY_IS_EQUAL(x, B(i,j));
    443         x = A(i,j);
    444         ++i;
    445       }
    446       ++j;
    447     }
    448     VERIFY_IS_APPROX(A,B);
    449     B.setRandom();
    450     
    451     i = 0;
    452     for(auto r : A.rowwise()) { VERIFY_IS_APPROX(r.sum(), A.row(i).sum()); ++i; }
    453     i = 0;
    454     for(auto r : B.rowwise()) { VERIFY_IS_APPROX(r.sum(), B.row(i).sum()); ++i; }
    455   }
    456 
    457 
    458   // check rows/cols iterators with STL algorithms
    459   {
    460     RowVectorType row = RowVectorType::Random(cols);
    461     A.rowwise() = row;
    462     VERIFY( std::all_of(A.rowwise().begin(),  A.rowwise().end(),  [&row](typename ColMatrixType::RowXpr x) { return internal::isApprox(x.squaredNorm(),row.squaredNorm()); }) );
    463     VERIFY( std::all_of(A.rowwise().rbegin(), A.rowwise().rend(), [&row](typename ColMatrixType::RowXpr x) { return internal::isApprox(x.squaredNorm(),row.squaredNorm()); }) );
    464 
    465     VectorType col = VectorType::Random(rows);
    466     A.colwise() = col;
    467     VERIFY( std::all_of(A.colwise().begin(),   A.colwise().end(),   [&col](typename ColMatrixType::ColXpr x) { return internal::isApprox(x.squaredNorm(),col.squaredNorm()); }) );
    468     VERIFY( std::all_of(A.colwise().rbegin(),  A.colwise().rend(),  [&col](typename ColMatrixType::ColXpr x) { return internal::isApprox(x.squaredNorm(),col.squaredNorm()); }) );
    469     VERIFY( std::all_of(A.colwise().cbegin(),  A.colwise().cend(),  [&col](typename ColMatrixType::ConstColXpr x) { return internal::isApprox(x.squaredNorm(),col.squaredNorm()); }) );
    470     VERIFY( std::all_of(A.colwise().crbegin(), A.colwise().crend(), [&col](typename ColMatrixType::ConstColXpr x) { return internal::isApprox(x.squaredNorm(),col.squaredNorm()); }) );
    471 
    472     i = internal::random<Index>(0,A.rows()-1);
    473     A.setRandom();
    474     A.row(i).setZero();
    475     VERIFY_IS_EQUAL( std::find_if(A.rowwise().begin(),  A.rowwise().end(),  [](typename ColMatrixType::RowXpr x) { return x.squaredNorm() == Scalar(0); })-A.rowwise().begin(),  i );
    476     VERIFY_IS_EQUAL( std::find_if(A.rowwise().rbegin(), A.rowwise().rend(), [](typename ColMatrixType::RowXpr x) { return x.squaredNorm() == Scalar(0); })-A.rowwise().rbegin(), (A.rows()-1) - i );
    477 
    478     j = internal::random<Index>(0,A.cols()-1);
    479     A.setRandom();
    480     A.col(j).setZero();
    481     VERIFY_IS_EQUAL( std::find_if(A.colwise().begin(),  A.colwise().end(),  [](typename ColMatrixType::ColXpr x) { return x.squaredNorm() == Scalar(0); })-A.colwise().begin(),  j );
    482     VERIFY_IS_EQUAL( std::find_if(A.colwise().rbegin(), A.colwise().rend(), [](typename ColMatrixType::ColXpr x) { return x.squaredNorm() == Scalar(0); })-A.colwise().rbegin(), (A.cols()-1) - j );
    483   }
    484 
    485   {
    486     using VecOp = VectorwiseOp<ArrayXXi, 0>;
    487     STATIC_CHECK(( internal::is_same<VecOp::const_iterator, decltype(std::declval<const VecOp&>().cbegin())>::value ));
    488     STATIC_CHECK(( internal::is_same<VecOp::const_iterator, decltype(std::declval<const VecOp&>().cend  ())>::value ));
    489     #if EIGEN_COMP_CXXVER>=14
    490       STATIC_CHECK(( internal::is_same<VecOp::const_iterator, decltype(std::cbegin(std::declval<const VecOp&>()))>::value ));
    491       STATIC_CHECK(( internal::is_same<VecOp::const_iterator, decltype(std::cend  (std::declval<const VecOp&>()))>::value ));
    492     #endif
    493   }
    494 
    495 #endif
    496 }
    497 
    498 
    499 #if EIGEN_HAS_CXX11
    500 // When the compiler sees expression IsContainerTest<C>(0), if C is an
    501 // STL-style container class, the first overload of IsContainerTest
    502 // will be viable (since both C::iterator* and C::const_iterator* are
    503 // valid types and NULL can be implicitly converted to them).  It will
    504 // be picked over the second overload as 'int' is a perfect match for
    505 // the type of argument 0.  If C::iterator or C::const_iterator is not
    506 // a valid type, the first overload is not viable, and the second
    507 // overload will be picked.
    508 template <class C,
    509           class Iterator = decltype(::std::declval<const C&>().begin()),
    510           class = decltype(::std::declval<const C&>().end()),
    511           class = decltype(++::std::declval<Iterator&>()),
    512           class = decltype(*::std::declval<Iterator>()),
    513           class = typename C::const_iterator>
    514 bool IsContainerType(int /* dummy */) { return true; }
    515 
    516 template <class C>
    517 bool IsContainerType(long /* dummy */) { return false; }
    518 
    519 template <typename Scalar, int Rows, int Cols>
    520 void test_stl_container_detection(int rows=Rows, int cols=Cols)
    521 {
    522   typedef Matrix<Scalar,Rows,1> VectorType;
    523   typedef Matrix<Scalar,Rows,Cols,ColMajor> ColMatrixType;
    524   typedef Matrix<Scalar,Rows,Cols,RowMajor> RowMatrixType;
    525 
    526   ColMatrixType A = ColMatrixType::Random(rows, cols);
    527   RowMatrixType B = RowMatrixType::Random(rows, cols);
    528 
    529   Index i = 1;
    530 
    531   using ColMatrixColType = decltype(A.col(i));
    532   using ColMatrixRowType = decltype(A.row(i));
    533   using RowMatrixColType = decltype(B.col(i));
    534   using RowMatrixRowType = decltype(B.row(i));
    535 
    536   // Vector and matrix col/row are valid Stl-style container.
    537   VERIFY_IS_EQUAL(IsContainerType<VectorType>(0), true);
    538   VERIFY_IS_EQUAL(IsContainerType<ColMatrixColType>(0), true);
    539   VERIFY_IS_EQUAL(IsContainerType<ColMatrixRowType>(0), true);
    540   VERIFY_IS_EQUAL(IsContainerType<RowMatrixColType>(0), true);
    541   VERIFY_IS_EQUAL(IsContainerType<RowMatrixRowType>(0), true);
    542 
    543   // But the matrix itself is not a valid Stl-style container.
    544   VERIFY_IS_EQUAL(IsContainerType<ColMatrixType>(0), rows == 1 || cols == 1);
    545   VERIFY_IS_EQUAL(IsContainerType<RowMatrixType>(0), rows == 1 || cols == 1);
    546 }
    547 #endif
    548 
    549 EIGEN_DECLARE_TEST(stl_iterators)
    550 {
    551   for(int i = 0; i < g_repeat; i++) {
    552     CALL_SUBTEST_1(( test_stl_iterators<double,2,3>() ));
    553     CALL_SUBTEST_1(( test_stl_iterators<float,7,5>() ));
    554     CALL_SUBTEST_1(( test_stl_iterators<int,Dynamic,Dynamic>(internal::random<int>(5,10), internal::random<int>(5,10)) ));
    555     CALL_SUBTEST_1(( test_stl_iterators<int,Dynamic,Dynamic>(internal::random<int>(10,200), internal::random<int>(10,200)) ));
    556   }
    557   
    558 #if EIGEN_HAS_CXX11
    559   CALL_SUBTEST_1(( test_stl_container_detection<float,1,1>() ));
    560   CALL_SUBTEST_1(( test_stl_container_detection<float,5,5>() ));
    561 #endif  
    562 }