Skip to content

Commit 0b039d0

Browse files
committed
More Tests: Cyclic
1 parent 19d3953 commit 0b039d0

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

tests/demo-lib/include/demo/Inheritance.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,33 @@ namespace demo
1414
struct Derived : MyBase {
1515
int count;
1616
};
17+
18+
// Cross-reference test (the "cyclic" case from issue #231 / PR #275):
19+
// ParIterBase is a base class for ParIter.
20+
// ParticleContainer references ParIter (via an alias).
21+
// ParIter.__init__ takes a ParticleContainer& (annotation back-reference).
22+
// This is NOT cyclic inheritance — just interleaved name usage.
23+
24+
struct ParIterBase {
25+
int level;
26+
};
27+
28+
struct ParticleContainer; // forward declaration
29+
30+
struct ParIter : ParIterBase {
31+
ParticleContainer* container;
32+
ParIter(ParticleContainer& pc, int level);
33+
};
34+
35+
struct ParticleContainer {
36+
std::string name;
37+
void process(ParIter& it);
38+
};
39+
40+
inline ParIter::ParIter(ParticleContainer& pc, int level)
41+
: container(&pc), ParIterBase{level} {}
42+
43+
inline void ParticleContainer::process(ParIter& it) {
44+
it.level += 1;
45+
}
1746
}

tests/py-demo/bindings/src/modules/classes.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,30 @@ void bind_classes_module(py::module&&m) {
3838
.def("g", &demo::Foo::Child::g);
3939
}
4040

41+
// Cross-reference / "cyclic" test case (issue #231, PR #275):
42+
// Registration order: ParticleContainer, then ParIter, then ParIterBase.
43+
// ParticleContainer.Iterator is an alias to ParIter (cross-ref).
44+
// ParIter inherits ParIterBase and takes ParticleContainer in __init__.
45+
// The topological sort must put ParIterBase before ParIter;
46+
// from __future__ import annotations handles the annotation back-refs.
47+
{
48+
auto pyParIterBase = py::class_<demo::ParIterBase>(m, "ParIterBase");
49+
pyParIterBase.def_readwrite("level", &demo::ParIterBase::level);
50+
51+
auto pyParticleContainer = py::class_<demo::ParticleContainer>(m, "ParticleContainer");
52+
pyParticleContainer.def_readwrite("name", &demo::ParticleContainer::name);
53+
54+
auto pyParIter = py::class_<demo::ParIter, demo::ParIterBase>(m, "ParIter");
55+
pyParIter.def(py::init<demo::ParticleContainer&, int>(),
56+
py::arg("particle_container"), py::arg("level"));
57+
58+
// Bind after ParIter is registered so pybind11 resolves the Python type
59+
pyParticleContainer.def("process", &demo::ParticleContainer::process);
60+
61+
// Alias: ParticleContainer.Iterator = ParIter
62+
pyParticleContainer.attr("Iterator") = pyParIter;
63+
}
64+
4165
{
4266
py::register_exception<demo::CppException>(m, "CppException");
4367
}

0 commit comments

Comments
 (0)