Segfault with std::forward invocation
A segfault showed up for me when upgrading flatsurf from cppyy 1.9.* to 2.1.0.
The problem seems to be related to move semantics and std::forward.
import cppyy
cppyy.include('gmpxx.h')
cppyy.load_library('gmp')
cppyy.load_library('gmpxx')
cppyy.cppdef(r'''
struct V {
V(mpq_class&& x, mpq_class&& y): x(std::move(x)), y(std::move(y)) {}
template <typename X, typename Y, std::enable_if_t<!std::is_convertible_v<X, mpq_class> || !std::is_convertible_v<Y, mpq_class>, int> = 0>
V(X&& x, Y&& y): V(static_cast<mpq_class>(std::forward<X>(x)), static_cast<mpq_class>(std::forward<Y>(y))) {}
mpq_class x,y;
};
''')
cppyy.cppdef(r'''
V f() {
return V(0, mpq_class{});
}
''')
print(cppyy.gbl.f()) # works
def f():
return cppyy.gbl.V(0, cppyy.gbl.mpq_class())
print(f()) # prints, then segfaults.
I might be doing something wrong here somehow but this used to work with older versions of cppyy.
I am seeing the segfault with the latest version of cppyy from conda-forge on Linux.
The Python code picks the second ctor, whereas the C++ call picks the first. To select the first also in Python, cppyy.gbl.V(0, cppyy.gbl.std.move(cppyy.gbl.mpq_class())) does the trick.
The problem appears to be that the template resolves to T*&& args, not T&&.
This is once more the trouble with Cling not providing any details what the template looks like, but only allowing to try guesses. That 0 means that typename X is going to map to int and things go downhill from there. Upstream is working on improving that, but it's going slow.