Exception message not properly propagated from inner nested class/struct
I realized that I cannot correctly printout my exceptions in case of nested classes.
If I have a class taking a nested class in ints ctor, I am getting an unclear message.
Minimal reproducer:
import cppyy
cppyy.cppdef("""
#include <stdexcept>
struct A {
struct B {
int x;
B(int xx) : x(xx) {
if (x > 42)
throw std::logic_error("My error!");
}
};
B b;
A(B bb) : b(bb) {}
};""")
from cppyy.gbl import A
b = A.B(200) # this throws the expected logical error:
# cppyy.gbl.std.logic_error: B::B(int xx) =>
# logic_error: My error!
a = A(200) # throws:
# TypeError: none of the 3 overloaded methods succeeded. Full details:
# A::A(A&&) =>
# TypeError: could not convert argument 1
# A::A(A::B bb) =>
# TypeError: could not convert argument 1
# A::A(const A&) =>
# TypeError: could not convert argument 1
The behaviour that I expect is, as in C++ in both cases to show the message, i.e.:
terminate called after throwing an instance of 'std::logic_error'
what(): My error!
It looks very much like a cppyy issue.
Related question: I wonder if there is a recommended workaround for such cases. I still want to be throwing from the inner class since it could be used on its own. But I want calling the ctor of the outer class to correctly complain.
The issue isn't nested classes, but rather that the second callrequires an implicit conversion, which is a concept that doesn't exist in Python. There is an implicit conversion mechanism in cppyy, but it fails b/c of the exception. The error reporting then still has to be at the level of A::A of which there are 3 overloads, not at the level of the single B failing. In C++, it's different b/c the overload is matched at compile time using the implicit conversion. Hence only 1 overload is ever tried, and it fails then as expected.
Only possible improvement might be to have A::A(A::B bb) report the C++ exception as part of the TypeError, but it makes no sense to have A(200) report only cppyy.gbl.std.logic_error from that single overload.