diff options
author | Gael Guennebaud <g.gael@free.fr> | 2016-09-05 15:50:41 +0200 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2016-09-05 15:50:41 +0200 |
commit | e13071dd13233b5d07e725453617c40421cf7501 (patch) | |
tree | 45b6dd14f402e6c217e2a22116716805b6e8095b /Eigen/src/Core | |
parent | d123717e21d6b0d073b3bf7ef96eae7c0651b3b3 (diff) |
Workaround a weird msvc 2012 compilation error.
Diffstat (limited to 'Eigen/src/Core')
-rw-r--r-- | Eigen/src/Core/CoreEvaluators.h | 55 | ||||
-rwxr-xr-x | Eigen/src/Core/util/Meta.h | 10 |
2 files changed, 60 insertions, 5 deletions
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<Scalar,NullaryOp,false,true,false> template<typename Scalar,typename NullaryOp> struct nullary_wrapper<Scalar,NullaryOp,false,false,false> {}; +#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<const MatrixXf> R = 2.f*A; +// and that has_*ary_operator<scalar_constant_op<float>> have not been instantiated yet. +// The "problem" is that evaluator<2.f*A> is instantiated by traits<Ref>::match<2.f*A> +// and at that time has_*ary_operator<T> 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<typename T> struct nullary_wrapper_workaround_msvc_2012 { + nullary_wrapper_workaround_msvc_2012(const T&); + operator T()const; +}; + +template<typename Scalar,typename NullaryOp> +struct nullary_wrapper<Scalar,NullaryOp,true,true,true> +{ + template <typename IndexType> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const { + return nullary_wrapper<Scalar,NullaryOp, + has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().operator()(op,i,j); + } + template <typename IndexType> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const { + return nullary_wrapper<Scalar,NullaryOp, + has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().operator()(op,i); + } + + template <typename T, typename IndexType> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const { + return nullary_wrapper<Scalar,NullaryOp, + has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().template packetOp<T>(op,i,j); + } + template <typename T, typename IndexType> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const { + return nullary_wrapper<Scalar,NullaryOp, + has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value, + has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().template packetOp<T>(op,i); + } +}; +#endif // MSVC<=2012 workaround + template<typename NullaryOp, typename PlainObjectType> struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> > : evaluator_base<CwiseNullaryOp<NullaryOp,PlainObjectType> > 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<typename T> const T& return_ref(); -template <typename T> +template <typename T, typename IndexType=Index> struct has_nullary_operator { template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()())>0)>::type * = 0); @@ -392,19 +392,19 @@ struct has_nullary_operator enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) }; }; -template <typename T> +template <typename T, typename IndexType=Index> struct has_unary_operator { - template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()(Index(0)))>0)>::type * = 0); + template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()(IndexType(0)))>0)>::type * = 0); static meta_no testFunctor(...); enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) }; }; -template <typename T> +template <typename T, typename IndexType=Index> struct has_binary_operator { - template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()(Index(0),Index(0)))>0)>::type * = 0); + template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ref<C>().operator()(IndexType(0),IndexType(0)))>0)>::type * = 0); static meta_no testFunctor(...); enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) }; |