问题
I have tried writing a function which takes a ColXpr
value as input:
typedef Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> Signal2D;
void Threshold(Signal2D::ColXpr& params)
{
params = (params >= 0.0f).template cast<float>();
}
When I try to call this function I do something like this:
Signal2D arr;
// fill it with stuff
Threshold(arr.col(0));
Then I get this compiler error:
src/core/Neuron.h:91:14: note: no known conversion for argument 1 from ‘Eigen::DenseBase<Eigen::Array<float, -1, -1> >::ColXpr {aka Eigen::Block<Eigen::Array<float, -1, -1>, -1, 1, true>}’ to ‘Eigen::DenseBase<Eigen::Array<float, -1, -1> >::ColXpr& {aka Eigen::Block<Eigen::Array<float, -1, -1>, -1, 1, true>&}’
make: *** [src/training/Fibonacci.o] Error 1
Without reposting the entire series of code that leads to this, could someone explain what it means when the compiler says no known conversion for argument from Value to Value&
? Why can't it get a reference in this instance? Note that I've seen a similar problem related to the this
pointer which I've posted here:
error: no match for 'operator<<' using boost::serialisation
Could this be some peculiarity of GCC 4.9.0 or am I doing something wrong here? Please let me know if you need to see a self-contained example, it will take a while to cobble together and I thought there might be enough info here to point out an obvious error on my part.
回答1:
In C++, a temporary object cannot bind to a non-const reference.
I'm assuming that arr.col(0)
returns an object by value. The returned value is a temporary object. This means it cannot match a parameter of type T &
.
One solution:
auto temp = arr.col(0);
Threshold(temp);
I wonder if you intended for arr.col()
to return a reference?
回答2:
To complete previous answers, you're probably looking for the Ref<>
class which will allow you to write a function that accept both columns of a matrix and vectors without templates nor copies:
void threshold(Ref<ArrayXf> params) {
params = (params >= 0 ).cast<float>();
}
ArrayXf a;
ArrayXXf A;
/* ... */
threshold(a);
threshold(A.col(j));
回答3:
To add to the answer above:
Eigen return expressions are temporaries. E.g. ColXpr
is just a small copyable object that gives you access to the array data. It is returned by value, ColXpr col(...)
. You can capture the ColXpr temporary with const reference but not otherwise.
However you can write:
void Threshold(Matrix::ColXpr col);
Generally, it is frowned upon to modify Eigen expression in functions. The preferred way is to write unary/binary functors/lambdas eg:
array.col(i) = array.col(i).unaryExpr(
[](const float &value) {
return float(value >= 0);
}
);
Btw, if you intend to write generic Eigen functions, use Eigen::EigenBase<B>
as arguments to capture any eigen expression, see http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html
Boost serialization requires non-temporary reference as well, even the operand is being written to an archive.
来源:https://stackoverflow.com/questions/23452961/no-known-expression-from-value-to-value-why