From b046a3f87d90d0f815dc03b9fdfcb1fda32504fb Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 6 Sep 2016 15:47:04 +0200 Subject: [PATCH] Workaround MSVC instantiation faillure of has_*ary_operator at the level of triats::match so that the has_*ary_operator are really properly instantiated throughout the compilation unit. --- Eigen/src/Core/CoreEvaluators.h | 34 ++++++++++++++++----------------- Eigen/src/Core/Ref.h | 8 +++++++- test/nullary.cpp | 15 +++++++++++++-- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index c5ad37847..ece8c0fcf 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -393,9 +393,9 @@ struct nullary_wrapper template struct nullary_wrapper {}; -#if EIGEN_COMP_MSVC>0 && EIGEN_COMP_MSVC<=1700 +#if EIGEN_COMP_MSVC>0 -// MSVC 2012 (and probably older ones too) exhibits a weird compilation error when +// MSVC exhibits a weird compilation error when // compiling: // Eigen::MatrixXf A = MatrixXf::Random(3,3); // Ref R = 2.f*A; @@ -408,8 +408,8 @@ struct nullary_wrapper {}; // This is a simple wrapper around Index to enforce the re-instantiation of // has_*ary_operator when needed. -template struct nullary_wrapper_workaround_msvc_2012 { - nullary_wrapper_workaround_msvc_2012(const T&); +template struct nullary_wrapper_workaround_msvc { + nullary_wrapper_workaround_msvc(const T&); operator T()const; }; @@ -419,34 +419,34 @@ struct nullary_wrapper template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const { return nullary_wrapper >::value, - has_unary_operator >::value, - has_binary_operator >::value>().operator()(op,i,j); + has_nullary_operator >::value, + has_unary_operator >::value, + has_binary_operator >::value>().operator()(op,i,j); } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { return nullary_wrapper >::value, - has_unary_operator >::value, - has_binary_operator >::value>().operator()(op,i); + has_nullary_operator >::value, + has_unary_operator >::value, + has_binary_operator >::value>().operator()(op,i); } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const { return nullary_wrapper >::value, - has_unary_operator >::value, - has_binary_operator >::value>().template packetOp(op,i,j); + has_nullary_operator >::value, + has_unary_operator >::value, + has_binary_operator >::value>().template packetOp(op,i,j); } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { return nullary_wrapper >::value, - has_unary_operator >::value, - has_binary_operator >::value>().template packetOp(op,i); + has_nullary_operator >::value, + has_unary_operator >::value, + has_binary_operator >::value>().template packetOp(op,i); } }; -#endif // MSVC<=2012 workaround +#endif // MSVC workaround template struct evaluator > diff --git a/Eigen/src/Core/Ref.h b/Eigen/src/Core/Ref.h index 17065fdd5..bdf24f52a 100644 --- a/Eigen/src/Core/Ref.h +++ b/Eigen/src/Core/Ref.h @@ -35,7 +35,13 @@ struct traits > || (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1), OuterStrideMatch = Derived::IsVectorAtCompileTime || int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime), - AlignmentMatch = (int(traits::Alignment)==int(Unaligned)) || (int(evaluator::Alignment) >= int(Alignment)), // FIXME the first condition is not very clear, it should be replaced by the required alignment + // NOTE, this indirection of evaluator::Alignment is needed + // to workaround a very strange bug in MSVC related to the instantiation + // of has_*ary_operator in evaluator. + // This line is surprisingly very sensitive. For instance, simply adding parenthesis + // as "DerivedAlignment = (int(evaluator::Alignment))," will make MSVC fail... + DerivedAlignment = int(evaluator::Alignment), + AlignmentMatch = (int(traits::Alignment)==int(Unaligned)) || (DerivedAlignment >= int(Alignment)), // FIXME the first condition is not very clear, it should be replaced by the required alignment ScalarTypeMatch = internal::is_same::value, MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch }; diff --git a/test/nullary.cpp b/test/nullary.cpp index a3c8b991e..9063c6de8 100644 --- a/test/nullary.cpp +++ b/test/nullary.cpp @@ -171,8 +171,9 @@ void test_nullary() VERIFY(( !internal::has_binary_operator >::value )); VERIFY(( internal::functor_has_linear_access >::ret )); - // Regression unit test for a weird MSVC 2012 bug. - // Search "nullary_wrapper_workaround_msvc_2012" in CoreEvaluators.h for the details. + // Regression unit test for a weird MSVC bug. + // Search "nullary_wrapper_workaround_msvc" in CoreEvaluators.h for the details. + // See also traits::match. { MatrixXf A = MatrixXf::Random(3,3); Ref R = 2.0*A; @@ -183,6 +184,16 @@ void test_nullary() VectorXi V = VectorXi::Random(3); Ref R2 = VectorXi::LinSpaced(3,1,3)+V; VERIFY_IS_APPROX(R2, V+Vector3i(1,2,3)); + + VERIFY(( internal::has_nullary_operator >::value )); + VERIFY(( !internal::has_unary_operator >::value )); + VERIFY(( !internal::has_binary_operator >::value )); + VERIFY(( internal::functor_has_linear_access >::ret )); + + VERIFY(( !internal::has_nullary_operator >::value )); + VERIFY(( internal::has_unary_operator >::value )); + VERIFY(( !internal::has_binary_operator >::value )); + VERIFY(( internal::functor_has_linear_access >::ret )); } #endif }