【发布时间】:2013-04-17 15:18:42
【问题描述】:
我正在为一个广泛使用 Eigen 的库编写代码,并且经常将 Eigen::Matrix 对象与我自己设计的 NSObject 子类 (vMAT_Array) 进行映射。使用该库通常需要将矩阵编组为 vMAT_Array 实例,以便它们可以被传递等等。
我有一个 vMAT_cast 模板函数来处理这个问题:
template <typename EigenObjectType>
vMAT_Array * vMAT_cast(EigenObjectType matrix)
{
return Map<EigenObjectType>(matrix).matA;
}
这个函数的问题是它不能与 Eigen 的惰性求值语义正确交互。以下面的单元测试代码为例:
vMAT_Array * matM = vMAT_cast(VectorXd::LinSpaced(40, 1.0, 40.0).eval());
[matM reshape:vMAT_MakeSize(5, 8)];
Mat<double> M = matM;
Array<bool, Dynamic, Dynamic> sel = M.unaryExpr([](double elt) { return (int)elt % 3 == 0; }).cast<bool>();
vMAT_Array * vecN = vMAT_pick(matM, vMAT_cast(sel));
NSLog(@"%@", vecN.dump);
vMAT_Array * vecNv = vMAT_cast(VectorXd::LinSpaced(13, 3.0, 39.0).eval());
STAssertEqualObjects(vecN, vecNv, @"Logical indexing broken");
注意.eval() 对vMAT_cast 的大多数参数的显式调用。这些是必要的,因为模板函数尝试(在编译时)使用 Eigen 的惰性表达式模板之一扩展为代码,该模板会生成如下可爱的错误消息:
/Users/Shared/Source/vMAT/vMATTests/EigenTests.mm:25:35: note: in instantiation of member function 'Eigen::DenseBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::LinSpaced' requested here
vMAT_Array * matM = vMAT_cast(VectorXd::LinSpaced(40, 1.0, 40.0));
^
In file included from /Users/Shared/Source/vMAT/vMATTests/EigenTests.mm:11:
In file included from /Users/Shared/Source/vMAT/vMAT/vMAT.h:51:
/Users/Shared/Source/vMAT/vMAT/vMAT_Array.h:122:82: error: no member named 'data' in 'Eigen::CwiseNullaryOp<Eigen::internal::linspaced_op<double, true>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >'
data:[NSMutableData dataWithBytes:matrix.data()
~~~~~~ ^
我怀疑有 template-fu 会“强制”MatrixBase::eval 发生,但我对此缺乏了解。谁能赐教?
【问题讨论】:
标签: templates objective-c++ eigen vmat