Reputation: 143
I'm doing a class in c++ to generalize two sparse matrix solvers (SparseLU and Sparse Cholesky). When I try to use the ternary operator it says that the operand types are incompatible, but if I use the If statement, the code compiles.
Error 2 error: operand types are incompatible ("const Eigen::Solve < Eigen::SimplicialLDLT < Eigen::SparseMatrix < double, 0, int > , 1, Eigen::AMDOrdering < int > > , Eigen::Matrix < double, -1, 1, 0, -1, 1 > > " and "const Eigen::Solve < Eigen::SparseLU < Eigen::SparseMatrix < double, 0, int > , Eigen::COLAMDOrdering < int > > , Eigen::Matrix < double, -1, 1, 0, -1, 1 > > ")
eigen::VectorXd solve(eigen::VectorXd &b) {
return is_cholesky ? cholesky.solve(b) : lu.solve(b); // ERROR
}
X
eigen::VectorXd solve(eigen::VectorXd &b) {
if (is_cholesky) {
return cholesky.solve(b);
}
else {
return lu.solve(b);
}
}
The whole code:
#pragma once
#ifndef SOLVER_H
#define SOLVER_H
#include <Eigen/Core>
#include <Eigen/Sparse>
#include <Eigen/SparseLU>
#include <Eigen/SparseCholesky>
#define eigen Eigen
class Solver {
private:
bool is_cholesky;
eigen::SimplicialLDLT<eigen::SparseMatrix<double>> cholesky;
eigen::SparseLU<eigen::SparseMatrix<double>> lu;
public:
Solver(bool is_choleski) {
this->is_cholesky = is_choleski;
}
eigen::ComputationInfo info() {
return is_cholesky ? cholesky.info() : lu.info();
}
void compute(eigen::SparseMatrix<double> &B) {
is_cholesky ? cholesky.compute(B) : lu.compute(B);
}
eigen::VectorXd solve(eigen::VectorXd &b) {
return is_cholesky ? cholesky.solve(b) : lu.solve(b); // ERROR HERE
}
};
#endif // SOLVER_H
Upvotes: 1
Views: 629
Reputation: 687
https://tmp.mosra.cz/eigen-docs/TopicPitfalls.html#TopicPitfalls_ternary_operator
Offical Documentation on http://eigen.tuxfamily.org/ is unavailable now, see also eigen/doc/Pitfalls.dox
Solution: return is_cholesky ? cholesky.solve(b).eval() : lu.solve(b);
Upvotes: 0
Reputation: 62719
The rules for the type of a a ? b : c
expression require that it is either the type of the b
expression or the type of the c
expression.
Here cholesky.solve(b)
has a type different to lu.solve(b)
and neither has an implicit conversion to the other. That the resulting expression will need a conversion to eigen::VectorXd
is ignored. Thus the "operand types are incompatible" error.
return is_cholesky ? cholesky.solve(b) : lu.solve(b); // ERROR
Here each expression directly has to have a conversion to eigen::VectorXd
, which exists.
if (is_cholesky) {
return cholesky.solve(b);
}
else {
return lu.solve(b);
}
You can force the type of the ?:
expression to eigen::VectorXd
by mentioning it explicitly, e.g.
return is_cholesky ? eigen::VectorXd{ cholesky.solve(b) } : lu.solve(b);
Upvotes: 5