mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-21 07:19:46 +08:00
Compile time detection for unimplemented stl-style iterators
This commit is contained in:
parent
3f2c8b7ff0
commit
c0ca8a9fa3
@ -583,11 +583,23 @@ template<typename Derived> class DenseBase
|
||||
typedef typename internal::conditional< (Flags&DirectAccessBit)==DirectAccessBit,
|
||||
internal::pointer_based_stl_iterator<Derived>,
|
||||
internal::generic_randaccess_stl_iterator<Derived>
|
||||
>::type iterator;
|
||||
>::type iterator_type;
|
||||
|
||||
typedef typename internal::conditional< (Flags&DirectAccessBit)==DirectAccessBit,
|
||||
internal::pointer_based_stl_iterator<const Derived>,
|
||||
internal::generic_randaccess_stl_iterator<const Derived>
|
||||
>::type const_iterator_type;
|
||||
|
||||
// Stl-style iterators are supported only for vectors.
|
||||
|
||||
typedef typename internal::conditional< IsVectorAtCompileTime,
|
||||
iterator_type,
|
||||
internal::not_an_iterator<const Derived>
|
||||
>::type iterator;
|
||||
|
||||
typedef typename internal::conditional< IsVectorAtCompileTime,
|
||||
const_iterator_type,
|
||||
internal::not_an_iterator<const Derived>
|
||||
>::type const_iterator;
|
||||
#endif
|
||||
|
||||
|
@ -11,6 +11,19 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Iterator type for XprType that do not support stl-style iterators. Allows to
|
||||
// detect that expression does not support stl iterators at compile time.
|
||||
template<typename XprType>
|
||||
class not_an_iterator
|
||||
{
|
||||
not_an_iterator() : mp_xpr(0), m_index(0) {}
|
||||
not_an_iterator(XprType& xpr, Index index) : mp_xpr(&xpr), m_index(index) {}
|
||||
|
||||
protected:
|
||||
XprType *mp_xpr;
|
||||
Index m_index;
|
||||
};
|
||||
|
||||
template<typename XprType,typename Derived>
|
||||
class indexed_based_stl_iterator_base
|
||||
{
|
||||
|
@ -135,6 +135,7 @@ template<typename Derived> class SolverBase;
|
||||
template<typename XprType> class InnerIterator;
|
||||
|
||||
namespace internal {
|
||||
template<typename XprType> class not_an_iterator;
|
||||
template<typename XprType> class generic_randaccess_stl_iterator;
|
||||
template<typename XprType> class pointer_based_stl_iterator;
|
||||
template<typename XprType, DirectionType Direction> class subvector_stl_iterator;
|
||||
|
@ -358,6 +358,59 @@ void test_stl_iterators(int rows=Rows, int cols=Cols)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
||||
// STL-style container class, the first overload of IsContainerTest
|
||||
// will be viable (since both C::iterator* and C::const_iterator* are
|
||||
// valid types and NULL can be implicitly converted to them). It will
|
||||
// be picked over the second overload as 'int' is a perfect match for
|
||||
// the type of argument 0. If C::iterator or C::const_iterator is not
|
||||
// a valid type, the first overload is not viable, and the second
|
||||
// overload will be picked.
|
||||
template <class C,
|
||||
class Iterator = decltype(::std::declval<const C&>().begin()),
|
||||
class = decltype(::std::declval<const C&>().end()),
|
||||
class = decltype(++::std::declval<Iterator&>()),
|
||||
class = decltype(*::std::declval<Iterator>()),
|
||||
class = typename C::const_iterator>
|
||||
bool IsContainerType(int /* dummy */) { return true; }
|
||||
|
||||
template <class C>
|
||||
bool IsContainerType(long /* dummy */) { return false; }
|
||||
#endif // EIGEN_HAS_CXX11
|
||||
|
||||
template <typename Scalar, int Rows, int Cols>
|
||||
void test_stl_container_detection(int rows=Rows, int cols=Cols)
|
||||
{
|
||||
#if EIGEN_HAS_CXX11
|
||||
typedef Matrix<Scalar,Rows,1> VectorType;
|
||||
typedef Matrix<Scalar,Rows,Cols,ColMajor> ColMatrixType;
|
||||
typedef Matrix<Scalar,Rows,Cols,RowMajor> RowMatrixType;
|
||||
|
||||
ColMatrixType A = ColMatrixType::Random(rows, cols);
|
||||
RowMatrixType B = RowMatrixType::Random(rows, cols);
|
||||
|
||||
Index i;
|
||||
|
||||
using ColMatrixColType = decltype(A.col(i));
|
||||
using ColMatrixRowType = decltype(A.row(i));
|
||||
using RowMatrixColType = decltype(B.col(i));
|
||||
using RowMatrixRowType = decltype(B.row(i));
|
||||
|
||||
// Vector and matrix col/row are valid Stl-style container.
|
||||
VERIFY_IS_EQUAL(IsContainerType<VectorType>(0), true);
|
||||
VERIFY_IS_EQUAL(IsContainerType<ColMatrixColType>(0), true);
|
||||
VERIFY_IS_EQUAL(IsContainerType<ColMatrixRowType>(0), true);
|
||||
VERIFY_IS_EQUAL(IsContainerType<RowMatrixColType>(0), true);
|
||||
VERIFY_IS_EQUAL(IsContainerType<RowMatrixRowType>(0), true);
|
||||
|
||||
// But the matrix itself is not a valid Stl-style container.
|
||||
VERIFY_IS_EQUAL(IsContainerType<ColMatrixType>(0), rows == 1 || cols == 1);
|
||||
VERIFY_IS_EQUAL(IsContainerType<RowMatrixType>(0), rows == 1 || cols == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(stl_iterators)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
@ -366,4 +419,7 @@ EIGEN_DECLARE_TEST(stl_iterators)
|
||||
CALL_SUBTEST_1(( test_stl_iterators<int,Dynamic,Dynamic>(internal::random<int>(5,10), internal::random<int>(5,10)) ));
|
||||
CALL_SUBTEST_1(( test_stl_iterators<int,Dynamic,Dynamic>(internal::random<int>(10,200), internal::random<int>(10,200)) ));
|
||||
}
|
||||
|
||||
CALL_SUBTEST_1(( test_stl_container_detection<float,1,1>() ));
|
||||
CALL_SUBTEST_1(( test_stl_container_detection<float,5,5>() ));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user