libigl-python-bindings icon indicating copy to clipboard operation
libigl-python-bindings copied to clipboard

Why does return require cast to double?

Open alecjacobson opened this issue 2 years ago • 3 comments

I'm trying to understand a compiler error and I think it's related to this choice:

https://github.com/libigl/libigl-python-bindings/blob/6bf30bcc3fc34c148da0bb9f029e181bf10f4d82/src/unproject_on_line.cpp#L72

How come double(t) is needed here rather than just t ?

alecjacobson avatar Apr 19 '22 22:04 alecjacobson

changing to t gives this error

...unproject_on_line.out.cpp:350:1: error: return type 'tuple<double, [...]>'
      must match previous return type 'tuple<float, [...]>' when lambda expression has unspecified explicit return type
return callit_unproject_on_line<Map_uv, Matrix_uv, Scalar_uv,Map_m, Matrix_m, Scalar_m,Map_vp, Matrix_vp, Scalar_vp,Map_origin, Matrix_origin, ...
^

Not sure how to parse that.

alecjacobson avatar Apr 19 '22 22:04 alecjacobson

Ah this is a gotcha in NPE:

Under the hood, NPE generates a templated function (in this case callit_unproject_on_line) with your code. It then generates a switch statement which calls this function with the appropriate types depending on what gets passed in to the python binding.

In the posted code, t has type npe_Scalar_uv which can be different depending on the type of uv. Thus, you end up with different return types for different template instantiations of callit_unproject_on_line which is not valid C++.

Note that npe::move handles this by casting your Eigen::Matrix types to PyObject* (or whatever pybind11's wrapper for this is) smartly (handing memory ownership and avoiding copies), so your return types always match with npe::move.

To return a single scalar, casting to the highest precision type seems like the reasonable thing to do here.

fwilliams avatar Apr 20 '22 17:04 fwilliams

Makes sense. Maybe to generate fewer templates t should just be defined to be double in the first place.

On Wed, Apr 20, 2022, 1:05 PM Francis Williams @.***> wrote:

Ah this is a gotcha in NPE:

Under the hood, NPE generates a templated function (in this case callit_unproject_on_line) with your code. It then generates a switch statement which calls this function with the appropriate types depending on what gets passed in to the python binding.

In the posted code, t has type npe_Scalar_uv which can be different depending on the type of uv. Thus, you end up with different return types for different template instantiations of callit_unproject_on_line which is not valid C++.

Note that npe::move handles this by casting your Eigen::Matrix types to PyObject* (or whatever pybind11's wrapper for this is) smartly (handing memory ownership and avoiding copies), so your return types always match with npe::move.

To return a single scalar, casting to the highest precision type seems like the reasonable thing to do here.

— Reply to this email directly, view it on GitHub https://github.com/libigl/libigl-python-bindings/issues/138#issuecomment-1104191270, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARDJGMSOLHD4FPXXBJ6ZS3VGA2OJANCNFSM5T2ICD7A . You are receiving this because you authored the thread.Message ID: @.***>

alecjacobson avatar Apr 20 '22 17:04 alecjacobson