user465139 - 3 months ago 21

C++ Question

I am in the process of wrapping a C++ library using Boost.Python. Some of the functions therein return

`Eigen::MatrixXd`

`operator()()`

`namespace bpy = boost::python;`

bpy::class_<Eigen::MatrixXd>("MatrixXd",

"Variable-size double-precision matrix class",

bpy::init<const Eigen::MatrixXd&>()

)

.def("__call__", static_cast<parop_signature>(&Eigen::MatrixXd::operator()))

// ...

;

The problem is that I cannot figure out what the correct signature of the function is. "Operationally" it should take two integer indices and return a double value. However,

`typedef const double& (Eigen::MatrixXd::*parop_signature)(int, int) const;`

results in the following compilation error (Mac OS X, clang++ in C++11 mode, Boost.Python V1.61):

`address of overloaded function 'operator()' cannot be static_cast to type`

'const double &(MatrixXd::*)(int, int) const'

...static_cast<const double& (Eigen::MatrixXd::*)(int, int) const>(&Eigen::MatrixXd::operator())

^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:111:41: note:

candidate function

EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const

^

/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:171:5: note:

candidate function

operator()(Index index) const

^

/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:334:5: note:

candidate function

operator()(Index row, Index col)

^

/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:392:5: note:

candidate function

operator()(Index index)

Fair enough, you'd say: but I cannot figure out how I can tell Boost.Python that

`CoeffReturnType`

`double`

`const double&`

`IndexType`

`int`

`typedef`

`const`

Even tried to declare a C++11 -style function pointer like

`auto eigen_indexfn = std::mem_fn<double(int,int)>(&Eigen::MatrixXd::operator());`

, no success, I get

`candidate template ignored: couldn't infer template argument '_Tp'`

mem_fn(_Rp _Tp::* __pm)

^

Is there someone who has gone through this already and can provide me with the correct signature of what for all intents and purposes should be as simple as "

`double Eigen::MatrixXd::operator(int, int)`

Answer

It seems the error origins from the fact that `Eigen::Index`

is not `int`

but defaults to `ptrdiff_t`

. Just because `int`

can implicitly be cast to `Eigen::Index`

does not mean that you can cast a function pointer which requires `Eigen::Index`

to a function pointer which requires `int`

. If that was possible, you would end up passing integers of the wrong size over the stack.

Addendum: If you really prefer `int`

over `ptrdiff_t`

, you can define `EIGEN_DEFAULT_DENSE_INDEX_TYPE`

to `int`

before including Eigen, as documented here, be aware that this will break ABI compatibility.