cppyy icon indicating copy to clipboard operation
cppyy copied to clipboard

Exception message not properly propagated from inner nested class/struct

Open ikabadzhov opened this issue 3 years ago • 1 comments

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.

ikabadzhov avatar Aug 17 '22 15:08 ikabadzhov

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.

wlav avatar Oct 08 '22 01:10 wlav