mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-21 00:59:36 +08:00
Workaround MSVC instantiation faillure of has_*ary_operator at the level of triats<Ref>::match so that the has_*ary_operator are really properly instantiated throughout the compilation unit.
This commit is contained in:
parent
3cb914f332
commit
b046a3f87d
@ -393,9 +393,9 @@ struct nullary_wrapper<Scalar,NullaryOp,false,true,false>
|
|||||||
template<typename Scalar,typename NullaryOp>
|
template<typename Scalar,typename NullaryOp>
|
||||||
struct nullary_wrapper<Scalar,NullaryOp,false,false,false> {};
|
struct nullary_wrapper<Scalar,NullaryOp,false,false,false> {};
|
||||||
|
|
||||||
#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:
|
// compiling:
|
||||||
// Eigen::MatrixXf A = MatrixXf::Random(3,3);
|
// Eigen::MatrixXf A = MatrixXf::Random(3,3);
|
||||||
// Ref<const MatrixXf> R = 2.f*A;
|
// Ref<const MatrixXf> R = 2.f*A;
|
||||||
@ -408,8 +408,8 @@ struct nullary_wrapper<Scalar,NullaryOp,false,false,false> {};
|
|||||||
|
|
||||||
// This is a simple wrapper around Index to enforce the re-instantiation of
|
// This is a simple wrapper around Index to enforce the re-instantiation of
|
||||||
// has_*ary_operator when needed.
|
// has_*ary_operator when needed.
|
||||||
template<typename T> struct nullary_wrapper_workaround_msvc_2012 {
|
template<typename T> struct nullary_wrapper_workaround_msvc {
|
||||||
nullary_wrapper_workaround_msvc_2012(const T&);
|
nullary_wrapper_workaround_msvc(const T&);
|
||||||
operator T()const;
|
operator T()const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -419,34 +419,34 @@ struct nullary_wrapper<Scalar,NullaryOp,true,true,true>
|
|||||||
template <typename IndexType>
|
template <typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const {
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i, IndexType j) const {
|
||||||
return nullary_wrapper<Scalar,NullaryOp,
|
return nullary_wrapper<Scalar,NullaryOp,
|
||||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().operator()(op,i,j);
|
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().operator()(op,i,j);
|
||||||
}
|
}
|
||||||
template <typename IndexType>
|
template <typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const {
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const NullaryOp& op, IndexType i) const {
|
||||||
return nullary_wrapper<Scalar,NullaryOp,
|
return nullary_wrapper<Scalar,NullaryOp,
|
||||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().operator()(op,i);
|
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().operator()(op,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename IndexType>
|
template <typename T, typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const {
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i, IndexType j) const {
|
||||||
return nullary_wrapper<Scalar,NullaryOp,
|
return nullary_wrapper<Scalar,NullaryOp,
|
||||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().template packetOp<T>(op,i,j);
|
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().template packetOp<T>(op,i,j);
|
||||||
}
|
}
|
||||||
template <typename T, typename IndexType>
|
template <typename T, typename IndexType>
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const {
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T packetOp(const NullaryOp& op, IndexType i) const {
|
||||||
return nullary_wrapper<Scalar,NullaryOp,
|
return nullary_wrapper<Scalar,NullaryOp,
|
||||||
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_nullary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value,
|
has_unary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value,
|
||||||
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc_2012<IndexType> >::value>().template packetOp<T>(op,i);
|
has_binary_operator<NullaryOp,nullary_wrapper_workaround_msvc<IndexType> >::value>().template packetOp<T>(op,i);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif // MSVC<=2012 workaround
|
#endif // MSVC workaround
|
||||||
|
|
||||||
template<typename NullaryOp, typename PlainObjectType>
|
template<typename NullaryOp, typename PlainObjectType>
|
||||||
struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
||||||
|
@ -35,7 +35,13 @@ struct traits<Ref<_PlainObjectType, _Options, _StrideType> >
|
|||||||
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
|
|| (int(StrideType::InnerStrideAtCompileTime)==0 && int(Derived::InnerStrideAtCompileTime)==1),
|
||||||
OuterStrideMatch = Derived::IsVectorAtCompileTime
|
OuterStrideMatch = Derived::IsVectorAtCompileTime
|
||||||
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
|
|| int(StrideType::OuterStrideAtCompileTime)==int(Dynamic) || int(StrideType::OuterStrideAtCompileTime)==int(Derived::OuterStrideAtCompileTime),
|
||||||
AlignmentMatch = (int(traits<PlainObjectType>::Alignment)==int(Unaligned)) || (int(evaluator<Derived>::Alignment) >= int(Alignment)), // FIXME the first condition is not very clear, it should be replaced by the required alignment
|
// NOTE, this indirection of evaluator<Derived>::Alignment is needed
|
||||||
|
// to workaround a very strange bug in MSVC related to the instantiation
|
||||||
|
// of has_*ary_operator in evaluator<CwiseNullaryOp>.
|
||||||
|
// This line is surprisingly very sensitive. For instance, simply adding parenthesis
|
||||||
|
// as "DerivedAlignment = (int(evaluator<Derived>::Alignment))," will make MSVC fail...
|
||||||
|
DerivedAlignment = int(evaluator<Derived>::Alignment),
|
||||||
|
AlignmentMatch = (int(traits<PlainObjectType>::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<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
|
ScalarTypeMatch = internal::is_same<typename PlainObjectType::Scalar, typename Derived::Scalar>::value,
|
||||||
MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
|
MatchAtCompileTime = HasDirectAccess && StorageOrderMatch && InnerStrideMatch && OuterStrideMatch && AlignmentMatch && ScalarTypeMatch
|
||||||
};
|
};
|
||||||
|
@ -171,8 +171,9 @@ void test_nullary()
|
|||||||
VERIFY(( !internal::has_binary_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 ));
|
VERIFY(( internal::functor_has_linear_access<internal::linspaced_op<float,float,false> >::ret ));
|
||||||
|
|
||||||
// Regression unit test for a weird MSVC 2012 bug.
|
// Regression unit test for a weird MSVC bug.
|
||||||
// Search "nullary_wrapper_workaround_msvc_2012" in CoreEvaluators.h for the details.
|
// Search "nullary_wrapper_workaround_msvc" in CoreEvaluators.h for the details.
|
||||||
|
// See also traits<Ref>::match.
|
||||||
{
|
{
|
||||||
MatrixXf A = MatrixXf::Random(3,3);
|
MatrixXf A = MatrixXf::Random(3,3);
|
||||||
Ref<const MatrixXf> R = 2.0*A;
|
Ref<const MatrixXf> R = 2.0*A;
|
||||||
@ -183,6 +184,16 @@ void test_nullary()
|
|||||||
VectorXi V = VectorXi::Random(3);
|
VectorXi V = VectorXi::Random(3);
|
||||||
Ref<const VectorXi> R2 = VectorXi::LinSpaced(3,1,3)+V;
|
Ref<const VectorXi> R2 = VectorXi::LinSpaced(3,1,3)+V;
|
||||||
VERIFY_IS_APPROX(R2, V+Vector3i(1,2,3));
|
VERIFY_IS_APPROX(R2, V+Vector3i(1,2,3));
|
||||||
|
|
||||||
|
VERIFY(( internal::has_nullary_operator<internal::scalar_constant_op<float> >::value ));
|
||||||
|
VERIFY(( !internal::has_unary_operator<internal::scalar_constant_op<float> >::value ));
|
||||||
|
VERIFY(( !internal::has_binary_operator<internal::scalar_constant_op<float> >::value ));
|
||||||
|
VERIFY(( internal::functor_has_linear_access<internal::scalar_constant_op<float> >::ret ));
|
||||||
|
|
||||||
|
VERIFY(( !internal::has_nullary_operator<internal::linspaced_op<int,int,false> >::value ));
|
||||||
|
VERIFY(( internal::has_unary_operator<internal::linspaced_op<int,int,false> >::value ));
|
||||||
|
VERIFY(( !internal::has_binary_operator<internal::linspaced_op<int,int,false> >::value ));
|
||||||
|
VERIFY(( internal::functor_has_linear_access<internal::linspaced_op<int,int,false> >::ret ));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user