From e13071dd13233b5d07e725453617c40421cf7501 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Mon, 5 Sep 2016 15:50:41 +0200 Subject: Workaround a weird msvc 2012 compilation error. --- Eigen/src/Core/CoreEvaluators.h | 55 +++++++++++++++++++++++++++++++++++++++++ Eigen/src/Core/util/Meta.h | 10 ++++---- 2 files changed, 60 insertions(+), 5 deletions(-) (limited to 'Eigen') diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index 9b90543c3..a3fb253c0 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -393,6 +393,61 @@ struct nullary_wrapper template struct nullary_wrapper {}; +#if EIGEN_COMP_MSVC>0 && EIGEN_COMP_MSVC<=1700 + +// MSVC 2012 (and probably older ones too) exhibits a weird compilation error when +// compiling: +// Eigen::MatrixXf A = MatrixXf::Random(3,3); +// Ref R = 2.f*A; +// and that has_*ary_operator> have not been instantiated yet. +// The "problem" is that evaluator<2.f*A> is instantiated by traits::match<2.f*A> +// and at that time has_*ary_operator returns true regardless of T. +// Then nullary_wrapper is badly instantiated as nullary_wrapper<.,.,true,true,true>. +// The trick is thus to defer the proper instantiation of nullary_wrapper when coeff(), +// and packet() are really instantiated as implemented below: + +// 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&); + operator T()const; +}; + +template +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); + } + 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); + } + + 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); + } + 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); + } +}; +#endif // MSVC<=2012 workaround + template struct evaluator > : evaluator_base > diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h index bbef83ea8..d4460bb77 100755 --- a/Eigen/src/Core/util/Meta.h +++ b/Eigen/src/Core/util/Meta.h @@ -383,7 +383,7 @@ struct has_ReturnType template const T& return_ref(); -template +template struct has_nullary_operator { template static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref().operator()())>0)>::type * = 0); @@ -392,19 +392,19 @@ struct has_nullary_operator enum { value = sizeof(testFunctor(static_cast(0))) == sizeof(meta_yes) }; }; -template +template struct has_unary_operator { - template static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref().operator()(Index(0)))>0)>::type * = 0); + template static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref().operator()(IndexType(0)))>0)>::type * = 0); static meta_no testFunctor(...); enum { value = sizeof(testFunctor(static_cast(0))) == sizeof(meta_yes) }; }; -template +template struct has_binary_operator { - template static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref().operator()(Index(0),Index(0)))>0)>::type * = 0); + template static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref().operator()(IndexType(0),IndexType(0)))>0)>::type * = 0); static meta_no testFunctor(...); enum { value = sizeof(testFunctor(static_cast(0))) == sizeof(meta_yes) }; -- cgit v1.2.3