Assigning a product to a triangularView, while using a custom Scalar type that has an explicit single-argument constructor taking an 'int', fails to compile.
When assigning a product to a triangularView, while using a custom Scalar type that has a single-argument constructor that is marked 'explicit' (which is good practice to prevent implicit conversions) taking an 'int', fails to compile (which is a bug / incorrect behavior).
Please see a code example here: https://godbolt.org/z/c9e1zE
The snippet is also copy-pasted into this issue, see further below.
The root of the problem is that in Eigen/src/Core/TriangularMatrix.h, calls like dst._assignProduct(src, 1, 0); fail to explicitly convert the second argument to Scalar.
Changing the following lines to:
line 971: dst._assignProduct(src, Scalar(1), 0);
resp.
line 982: dst._assignProduct(src, Scalar(1), 1);
and
line 993 dst._assignProduct(src, Scalar(-1), 1);
seems to fix the problem.
kind regards, Niek
#include <Eigen/Dense>
#include <iostream>
#include <vector>
class my_int
{
int v_;
public:
my_int() = default;
// UNCOMMENT THE LINE BELOW TO MAKE THIS EXAMPLE COMPILE
explicit
my_int(int x)
: v_(x)
{}
private:
inline friend std::ostream& operator<<(std::ostream& os, const my_int& obj)
{
return os << obj.v_;
}
inline friend my_int operator*(my_int const& a, my_int const& b)
{
return my_int {a.v_ * b.v_};
}
inline friend my_int operator+(my_int const& a, my_int const& b)
{
return my_int {a.v_ + b.v_};
}
inline friend my_int& operator+=(my_int& a, my_int const& b)
{
a.v_ += b.v_;
return a;
}
};
// boilerplate for my custom scalar type
namespace Eigen {
template <>
struct NumTraits<my_int> : Eigen::GenericNumTraits<my_int>
{
using Real = my_int;
using NonInteger = my_int;
using Literal = my_int;
using Nested = my_int;
static inline Real epsilon()
{
return my_int{0};
}
static inline Real dummy_precision()
{
return my_int{0};
}
static inline int digits10()
{
return 0;
}
enum {
IsComplex = 0,
IsInteger = 1,
IsSigned = 1,
RequireInitialization = 1,
ReadCost = 1,
AddCost = 1,
MulCost = 1
};
};
}
int main() {
using std::cout;
using myint_mat = Eigen::Matrix<my_int, Eigen::Dynamic, Eigen::Dynamic>;
using int_mat = Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic>;
myint_mat A (2,2);
{
int_mat iA (2,2);
iA << 1,2,3,4;
A = iA.cast<my_int>();
}
myint_mat B (2,2);
{
int_mat iB (2,2);
iB << 5,6,7,8;
B = iB.cast<my_int>();
}
// THIS LINE BELOW TRIGGERS THE COMPILATION ERROR
A.template triangularView<Eigen::Upper>() = B * B;
cout << A << '\n';
}