@@ -145,16 +145,147 @@ class NCVirtTrampoline : public NCVirt {
145
145
}
146
146
};
147
147
148
- int runExampleVirt (ExampleVirt *ex, int value) {
149
- return ex->run (value);
150
- }
148
+ struct Base {
149
+ /* for some reason MSVC2015 can't compile this if the function is pure virtual */
150
+ virtual std::string dispatch () const { return {}; };
151
+ };
151
152
152
- bool runExampleVirtBool (ExampleVirt* ex) {
153
- return ex->run_bool ();
154
- }
153
+ struct DispatchIssue : Base {
154
+ virtual std::string dispatch () const {
155
+ PYBIND11_OVERLOAD_PURE (std::string, Base, dispatch, /* no arguments */ );
156
+ }
157
+ };
158
+
159
+ // Forward declaration (so that we can put the main tests here; the inherited virtual approaches are
160
+ // rather long).
161
+ void initialize_inherited_virtuals (py::module &m);
162
+
163
+ TEST_SUBMODULE (virtual_functions, m) {
164
+ // test_override
165
+ py::class_<ExampleVirt, PyExampleVirt>(m, " ExampleVirt" )
166
+ .def (py::init<int >())
167
+ /* Reference original class in function definitions */
168
+ .def (" run" , &ExampleVirt::run)
169
+ .def (" run_bool" , &ExampleVirt::run_bool)
170
+ .def (" pure_virtual" , &ExampleVirt::pure_virtual);
171
+
172
+ py::class_<NonCopyable>(m, " NonCopyable" )
173
+ .def (py::init<int , int >());
174
+
175
+ py::class_<Movable>(m, " Movable" )
176
+ .def (py::init<int , int >());
177
+
178
+ // test_move_support
179
+ #if !defined(__INTEL_COMPILER)
180
+ py::class_<NCVirt, NCVirtTrampoline>(m, " NCVirt" )
181
+ .def (py::init<>())
182
+ .def (" get_noncopyable" , &NCVirt::get_noncopyable)
183
+ .def (" get_movable" , &NCVirt::get_movable)
184
+ .def (" print_nc" , &NCVirt::print_nc)
185
+ .def (" print_movable" , &NCVirt::print_movable);
186
+ #endif
187
+
188
+ m.def (" runExampleVirt" , [](ExampleVirt *ex, int value) { return ex->run (value); });
189
+ m.def (" runExampleVirtBool" , [](ExampleVirt* ex) { return ex->run_bool (); });
190
+ m.def (" runExampleVirtVirtual" , [](ExampleVirt *ex) { ex->pure_virtual (); });
191
+
192
+ m.def (" cstats_debug" , &ConstructorStats::get<ExampleVirt>);
193
+ initialize_inherited_virtuals (m);
194
+
195
+ // test_alias_delay_initialization1
196
+ // don't invoke Python dispatch classes by default when instantiating C++ classes
197
+ // that were not extended on the Python side
198
+ struct A {
199
+ virtual ~A () {}
200
+ virtual void f () { py::print (" A.f()" ); }
201
+ };
202
+
203
+ struct PyA : A {
204
+ PyA () { py::print (" PyA.PyA()" ); }
205
+ ~PyA () { py::print (" PyA.~PyA()" ); }
206
+
207
+ void f () override {
208
+ py::print (" PyA.f()" );
209
+ PYBIND11_OVERLOAD (void , A, f);
210
+ }
211
+ };
212
+
213
+ py::class_<A, PyA>(m, " A" )
214
+ .def (py::init<>())
215
+ .def (" f" , &A::f);
216
+
217
+ m.def (" call_f" , [](A *a) { a->f (); });
218
+
219
+ // test_alias_delay_initialization2
220
+ // ... unless we explicitly request it, as in this example:
221
+ struct A2 {
222
+ virtual ~A2 () {}
223
+ virtual void f () { py::print (" A2.f()" ); }
224
+ };
225
+
226
+ struct PyA2 : A2 {
227
+ PyA2 () { py::print (" PyA2.PyA2()" ); }
228
+ ~PyA2 () { py::print (" PyA2.~PyA2()" ); }
229
+ void f () override {
230
+ py::print (" PyA2.f()" );
231
+ PYBIND11_OVERLOAD (void , A2, f);
232
+ }
233
+ };
234
+
235
+ py::class_<A2, PyA2>(m, " A2" )
236
+ .def (py::init_alias<>())
237
+ .def (" f" , &A2::f);
238
+
239
+ m.def (" call_f" , [](A2 *a2) { a2->f (); });
240
+
241
+ // test_dispatch_issue
242
+ // #159: virtual function dispatch has problems with similar-named functions
243
+ py::class_<Base, DispatchIssue>(m, " DispatchIssue" )
244
+ .def (py::init<>())
245
+ .def (" dispatch" , &Base::dispatch);
246
+
247
+ m.def (" dispatch_issue_go" , [](const Base * b) { return b->dispatch (); });
248
+
249
+ // test_override_ref
250
+ // #392/397: overridding reference-returning functions
251
+ class OverrideTest {
252
+ public:
253
+ struct A { std::string value = " hi" ; };
254
+ std::string v;
255
+ A a;
256
+ explicit OverrideTest (const std::string &v) : v{v} {}
257
+ virtual std::string str_value () { return v; }
258
+ virtual std::string &str_ref () { return v; }
259
+ virtual A A_value () { return a; }
260
+ virtual A &A_ref () { return a; }
261
+ };
155
262
156
- void runExampleVirtVirtual (ExampleVirt *ex) {
157
- ex->pure_virtual ();
263
+ class PyOverrideTest : public OverrideTest {
264
+ public:
265
+ using OverrideTest::OverrideTest;
266
+ std::string str_value () override { PYBIND11_OVERLOAD (std::string, OverrideTest, str_value); }
267
+ // Not allowed (uncommenting should hit a static_assert failure): we can't get a reference
268
+ // to a python numeric value, since we only copy values in the numeric type caster:
269
+ // std::string &str_ref() override { PYBIND11_OVERLOAD(std::string &, OverrideTest, str_ref); }
270
+ // But we can work around it like this:
271
+ private:
272
+ std::string _tmp;
273
+ std::string str_ref_helper () { PYBIND11_OVERLOAD (std::string, OverrideTest, str_ref); }
274
+ public:
275
+ std::string &str_ref () override { return _tmp = str_ref_helper (); }
276
+
277
+ A A_value () override { PYBIND11_OVERLOAD (A, OverrideTest, A_value); }
278
+ A &A_ref () override { PYBIND11_OVERLOAD (A &, OverrideTest, A_ref); }
279
+ };
280
+
281
+ py::class_<OverrideTest::A>(m, " OverrideTest_A" )
282
+ .def_readwrite (" value" , &OverrideTest::A::value);
283
+ py::class_<OverrideTest, PyOverrideTest>(m, " OverrideTest" )
284
+ .def (py::init<const std::string &>())
285
+ .def (" str_value" , &OverrideTest::str_value)
286
+ // .def("str_ref", &OverrideTest::str_ref)
287
+ .def (" A_value" , &OverrideTest::A_value)
288
+ .def (" A_ref" , &OverrideTest::A_ref);
158
289
}
159
290
160
291
@@ -281,6 +412,8 @@ template <class Base = D_Tpl> class PyD_Tpl : public PyC_Tpl<Base> {
281
412
282
413
283
414
void initialize_inherited_virtuals (py::module &m) {
415
+ // test_inherited_virtuals
416
+
284
417
// Method 1: repeat
285
418
py::class_<A_Repeat, PyA_Repeat>(m, " A_Repeat" )
286
419
.def (py::init<>())
@@ -295,6 +428,7 @@ void initialize_inherited_virtuals(py::module &m) {
295
428
py::class_<D_Repeat, C_Repeat, PyD_Repeat>(m, " D_Repeat" )
296
429
.def (py::init<>());
297
430
431
+ // test_
298
432
// Method 2: Templated trampolines
299
433
py::class_<A_Tpl, PyA_Tpl<>>(m, " A_Tpl" )
300
434
.def (py::init<>())
@@ -311,137 +445,3 @@ void initialize_inherited_virtuals(py::module &m) {
311
445
312
446
};
313
447
314
- struct Base {
315
- /* for some reason MSVC2015 can't compile this if the function is pure virtual */
316
- virtual std::string dispatch () const { return {}; };
317
- };
318
-
319
- struct DispatchIssue : Base {
320
- virtual std::string dispatch () const {
321
- PYBIND11_OVERLOAD_PURE (std::string, Base, dispatch, /* no arguments */ );
322
- }
323
- };
324
-
325
- TEST_SUBMODULE (virtual_functions, m) {
326
- py::class_<ExampleVirt, PyExampleVirt>(m, " ExampleVirt" )
327
- .def (py::init<int >())
328
- /* Reference original class in function definitions */
329
- .def (" run" , &ExampleVirt::run)
330
- .def (" run_bool" , &ExampleVirt::run_bool)
331
- .def (" pure_virtual" , &ExampleVirt::pure_virtual);
332
-
333
- py::class_<NonCopyable>(m, " NonCopyable" )
334
- .def (py::init<int , int >());
335
-
336
- py::class_<Movable>(m, " Movable" )
337
- .def (py::init<int , int >());
338
-
339
- #if !defined(__INTEL_COMPILER)
340
- py::class_<NCVirt, NCVirtTrampoline>(m, " NCVirt" )
341
- .def (py::init<>())
342
- .def (" get_noncopyable" , &NCVirt::get_noncopyable)
343
- .def (" get_movable" , &NCVirt::get_movable)
344
- .def (" print_nc" , &NCVirt::print_nc)
345
- .def (" print_movable" , &NCVirt::print_movable);
346
- #endif
347
-
348
- m.def (" runExampleVirt" , &runExampleVirt);
349
- m.def (" runExampleVirtBool" , &runExampleVirtBool);
350
- m.def (" runExampleVirtVirtual" , &runExampleVirtVirtual);
351
-
352
- m.def (" cstats_debug" , &ConstructorStats::get<ExampleVirt>);
353
- initialize_inherited_virtuals (m);
354
-
355
- // test_alias_delay_initialization1
356
- // don't invoke Python dispatch classes by default when instantiating C++ classes
357
- // that were not extended on the Python side
358
- struct A {
359
- virtual ~A () {}
360
- virtual void f () { py::print (" A.f()" ); }
361
- };
362
-
363
- struct PyA : A {
364
- PyA () { py::print (" PyA.PyA()" ); }
365
- ~PyA () { py::print (" PyA.~PyA()" ); }
366
-
367
- void f () override {
368
- py::print (" PyA.f()" );
369
- PYBIND11_OVERLOAD (void , A, f);
370
- }
371
- };
372
-
373
- py::class_<A, PyA>(m, " A" )
374
- .def (py::init<>())
375
- .def (" f" , &A::f);
376
-
377
- m.def (" call_f" , [](A *a) { a->f (); });
378
-
379
- // test_alias_delay_initialization2
380
- // ... unless we explicitly request it, as in this example:
381
- struct A2 {
382
- virtual ~A2 () {}
383
- virtual void f () { py::print (" A2.f()" ); }
384
- };
385
-
386
- struct PyA2 : A2 {
387
- PyA2 () { py::print (" PyA2.PyA2()" ); }
388
- ~PyA2 () { py::print (" PyA2.~PyA2()" ); }
389
- void f () override {
390
- py::print (" PyA2.f()" );
391
- PYBIND11_OVERLOAD (void , A2, f);
392
- }
393
- };
394
-
395
- py::class_<A2, PyA2>(m, " A2" )
396
- .def (py::init_alias<>())
397
- .def (" f" , &A2::f);
398
-
399
- m.def (" call_f" , [](A2 *a2) { a2->f (); });
400
-
401
- // #159: virtual function dispatch has problems with similar-named functions
402
- py::class_<Base, DispatchIssue>(m, " DispatchIssue" )
403
- .def (py::init<>())
404
- .def (" dispatch" , &Base::dispatch);
405
-
406
- m.def (" dispatch_issue_go" , [](const Base * b) { return b->dispatch (); });
407
-
408
- // #392/397: overridding reference-returning functions
409
- class OverrideTest {
410
- public:
411
- struct A { std::string value = " hi" ; };
412
- std::string v;
413
- A a;
414
- explicit OverrideTest (const std::string &v) : v{v} {}
415
- virtual std::string str_value () { return v; }
416
- virtual std::string &str_ref () { return v; }
417
- virtual A A_value () { return a; }
418
- virtual A &A_ref () { return a; }
419
- };
420
-
421
- class PyOverrideTest : public OverrideTest {
422
- public:
423
- using OverrideTest::OverrideTest;
424
- std::string str_value () override { PYBIND11_OVERLOAD (std::string, OverrideTest, str_value); }
425
- // Not allowed (uncommenting should hit a static_assert failure): we can't get a reference
426
- // to a python numeric value, since we only copy values in the numeric type caster:
427
- // std::string &str_ref() override { PYBIND11_OVERLOAD(std::string &, OverrideTest, str_ref); }
428
- // But we can work around it like this:
429
- private:
430
- std::string _tmp;
431
- std::string str_ref_helper () { PYBIND11_OVERLOAD (std::string, OverrideTest, str_ref); }
432
- public:
433
- std::string &str_ref () override { return _tmp = str_ref_helper (); }
434
-
435
- A A_value () override { PYBIND11_OVERLOAD (A, OverrideTest, A_value); }
436
- A &A_ref () override { PYBIND11_OVERLOAD (A &, OverrideTest, A_ref); }
437
- };
438
-
439
- py::class_<OverrideTest::A>(m, " OverrideTest_A" )
440
- .def_readwrite (" value" , &OverrideTest::A::value);
441
- py::class_<OverrideTest, PyOverrideTest>(m, " OverrideTest" )
442
- .def (py::init<const std::string &>())
443
- .def (" str_value" , &OverrideTest::str_value)
444
- // .def("str_ref", &OverrideTest::str_ref)
445
- .def (" A_value" , &OverrideTest::A_value)
446
- .def (" A_ref" , &OverrideTest::A_ref);
447
- }
0 commit comments