mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-03-13 18:37:27 +08:00
Workaround a weird msvc 2012 compilation error.
This commit is contained in:
parent
d123717e21
commit
e13071dd13
@ -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> >
|
||||
|
@ -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) };
|
||||
|
@ -170,5 +170,19 @@ void test_nullary()
|
||||
VERIFY(( internal::has_unary_operator<internal::linspaced_op<float,float,false> >::value ));
|
||||
VERIFY(( !internal::has_binary_operator<internal::linspaced_op<float,float,false> >::value ));
|
||||
VERIFY(( internal::functor_has_linear_access<internal::linspaced_op<float,float,false> >::ret ));
|
||||
|
||||
// Regression unit test for a weird MSVC 2012 bug.
|
||||
// Search "nullary_wrapper_workaround_msvc_2012" in CoreEvaluators.h for the details.
|
||||
{
|
||||
MatrixXf A = MatrixXf::Random(3,3);
|
||||
Ref<const MatrixXf> R = 2.0*A;
|
||||
VERIFY_IS_APPROX(R, A+A);
|
||||
|
||||
Ref<const MatrixXf> R1 = MatrixXf::Random(3,3)+A;
|
||||
|
||||
VectorXi V = VectorXi::Random(3);
|
||||
Ref<const VectorXi> R2 = VectorXi::LinSpaced(3,1,3)+V;
|
||||
VERIFY_IS_APPROX(R2, V+Vector3i(1,2,3));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user