μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
test_virtual_functions.cpp
Go to the documentation of this file.
1/*
2 tests/test_virtual_functions.cpp -- overriding virtual functions from Python
3
4 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
10#include <pybind11/functional.h>
11
12#include "constructor_stats.h"
13#include "pybind11_tests.h"
14
15#include <thread>
16
17/* This is an example class that we'll want to be able to extend from Python */
18class ExampleVirt {
19public:
20 explicit ExampleVirt(int state) : state(state) { print_created(this, state); }
22 ExampleVirt(ExampleVirt &&e) noexcept : state(e.state) {
24 e.state = 0;
25 }
26 virtual ~ExampleVirt() { print_destroyed(this); }
27
28 virtual int run(int value) {
29 py::print("Original implementation of "
30 "ExampleVirt::run(state={}, value={}, str1={}, str2={})"_s.format(
31 state, value, get_string1(), *get_string2()));
32 return state + value;
33 }
34
35 virtual bool run_bool() = 0;
36 virtual void pure_virtual() = 0;
37
38 // Returning a reference/pointer to a type converted from python (numbers, strings, etc.) is a
39 // bit trickier, because the actual int& or std::string& or whatever only exists temporarily,
40 // so we have to handle it specially in the trampoline class (see below).
41 virtual const std::string &get_string1() { return str1; }
42 virtual const std::string *get_string2() { return &str2; }
43
44private:
45 int state;
46 const std::string str1{"default1"}, str2{"default2"};
47};
48
49/* This is a wrapper class that must be generated */
50class PyExampleVirt : public ExampleVirt {
51public:
52 using ExampleVirt::ExampleVirt; /* Inherit constructors */
53
54 int run(int value) override {
55 /* Generate wrapping code that enables native function overloading */
56 PYBIND11_OVERRIDE(int, /* Return type */
57 ExampleVirt, /* Parent class */
58 run, /* Name of function */
59 value /* Argument(s) */
60 );
61 }
62
63 bool run_bool() override {
64 PYBIND11_OVERRIDE_PURE(bool, /* Return type */
65 ExampleVirt, /* Parent class */
66 run_bool, /* Name of function */
67 /* This function has no arguments. The trailing comma
68 in the previous line is needed for some compilers */
69 );
70 }
71
72 void pure_virtual() override {
73 PYBIND11_OVERRIDE_PURE(void, /* Return type */
74 ExampleVirt, /* Parent class */
75 pure_virtual, /* Name of function */
76 /* This function has no arguments. The trailing comma
77 in the previous line is needed for some compilers */
78 );
79 }
80
81 // We can return reference types for compatibility with C++ virtual interfaces that do so, but
82 // note they have some significant limitations (see the documentation).
83 const std::string &get_string1() override {
84 PYBIND11_OVERRIDE(const std::string &, /* Return type */
85 ExampleVirt, /* Parent class */
86 get_string1, /* Name of function */
87 /* (no arguments) */
88 );
89 }
90
91 const std::string *get_string2() override {
92 PYBIND11_OVERRIDE(const std::string *, /* Return type */
93 ExampleVirt, /* Parent class */
94 get_string2, /* Name of function */
95 /* (no arguments) */
96 );
97 }
98};
99
100class NonCopyable {
101public:
102 NonCopyable(int a, int b) : value{new int(a * b)} { print_created(this, a, b); }
103 NonCopyable(NonCopyable &&o) noexcept : value{std::move(o.value)} { print_move_created(this); }
104 NonCopyable(const NonCopyable &) = delete;
105 NonCopyable() = delete;
106 void operator=(const NonCopyable &) = delete;
107 void operator=(NonCopyable &&) = delete;
108 std::string get_value() const {
109 if (value) {
110 return std::to_string(*value);
111 }
112 return "(null)";
113 }
115
116private:
117 std::unique_ptr<int> value;
118};
119
120// This is like the above, but is both copy and movable. In effect this means it should get moved
121// when it is not referenced elsewhere, but copied if it is still referenced.
122class Movable {
123public:
124 Movable(int a, int b) : value{a + b} { print_created(this, a, b); }
125 Movable(const Movable &m) : value{m.value} { print_copy_created(this); }
126 Movable(Movable &&m) noexcept : value{m.value} { print_move_created(this); }
127 std::string get_value() const { return std::to_string(value); }
129
130private:
131 int value;
132};
133
134class NCVirt {
135public:
136 virtual ~NCVirt() = default;
137 NCVirt() = default;
138 NCVirt(const NCVirt &) = delete;
139 virtual NonCopyable get_noncopyable(int a, int b) { return NonCopyable(a, b); }
140 virtual Movable get_movable(int a, int b) = 0;
141
142 std::string print_nc(int a, int b) { return get_noncopyable(a, b).get_value(); }
143 std::string print_movable(int a, int b) { return get_movable(a, b).get_value(); }
144};
145class NCVirtTrampoline : public NCVirt {
146#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
147 NonCopyable get_noncopyable(int a, int b) override {
149 }
150#endif
151 Movable get_movable(int a, int b) override {
153 }
154};
155
156struct Base {
157 virtual std::string dispatch() const = 0;
158 virtual ~Base() = default;
159 Base() = default;
160 Base(const Base &) = delete;
161};
162
163struct DispatchIssue : Base {
164 std::string dispatch() const override {
165 PYBIND11_OVERRIDE_PURE(std::string, Base, dispatch, /* no arguments */);
166 }
167};
168
169// An abstract adder class that uses visitor pattern to add two data
170// objects and send the result to the visitor functor
171struct AdderBase {
172 struct Data {};
173 using DataVisitor = std::function<void(const Data &)>;
174
175 virtual void
176 operator()(const Data &first, const Data &second, const DataVisitor &visitor) const
177 = 0;
178 virtual ~AdderBase() = default;
179 AdderBase() = default;
180 AdderBase(const AdderBase &) = delete;
181};
182
183struct Adder : AdderBase {
184 void
185 operator()(const Data &first, const Data &second, const DataVisitor &visitor) const override {
187 void, AdderBase, "__call__", operator(), first, second, visitor);
188 }
189};
190
191static void test_gil() {
192 {
193 py::gil_scoped_acquire lock;
194 py::print("1st lock acquired");
195 }
196
197 {
198 py::gil_scoped_acquire lock;
199 py::print("2nd lock acquired");
200 }
201}
202
203static void test_gil_from_thread() {
204 py::gil_scoped_release release;
205
206 std::thread t(test_gil);
207 t.join();
208}
209
211
212public:
213 virtual int func() { return 0; }
214
216 virtual ~test_override_cache_helper() = default;
217 // Non-copyable
220};
221
224};
225
226inline int test_override_cache(std::shared_ptr<test_override_cache_helper> const &instance) {
227 return instance->func();
228}
229
230// Forward declaration (so that we can put the main tests here; the inherited virtual approaches
231// are rather long).
232void initialize_inherited_virtuals(py::module_ &m);
233
234TEST_SUBMODULE(virtual_functions, m) {
235 // test_override
236 py::class_<ExampleVirt, PyExampleVirt>(m, "ExampleVirt")
237 .def(py::init<int>())
238 /* Reference original class in function definitions */
239 .def("run", &ExampleVirt::run)
240 .def("run_bool", &ExampleVirt::run_bool)
241 .def("pure_virtual", &ExampleVirt::pure_virtual);
242
243 py::class_<NonCopyable>(m, "NonCopyable").def(py::init<int, int>());
244
245 py::class_<Movable>(m, "Movable").def(py::init<int, int>());
246
247 // test_move_support
248#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
249 py::class_<NCVirt, NCVirtTrampoline>(m, "NCVirt")
250 .def(py::init<>())
251 .def("get_noncopyable", &NCVirt::get_noncopyable)
252 .def("get_movable", &NCVirt::get_movable)
253 .def("print_nc", &NCVirt::print_nc)
254 .def("print_movable", &NCVirt::print_movable);
255#endif
256
257 m.def("runExampleVirt", [](ExampleVirt *ex, int value) { return ex->run(value); });
258 m.def("runExampleVirtBool", [](ExampleVirt *ex) { return ex->run_bool(); });
259 m.def("runExampleVirtVirtual", [](ExampleVirt *ex) { ex->pure_virtual(); });
260
261 m.def("cstats_debug", &ConstructorStats::get<ExampleVirt>);
263
264 // test_alias_delay_initialization1
265 // don't invoke Python dispatch classes by default when instantiating C++ classes
266 // that were not extended on the Python side
267 struct A {
268 A() = default;
269 A(const A &) = delete;
270 virtual ~A() = default;
271 virtual void f() { py::print("A.f()"); }
272 };
273
274 struct PyA : A {
275 PyA() { py::print("PyA.PyA()"); }
276 PyA(const PyA &) = delete;
277 ~PyA() override { py::print("PyA.~PyA()"); }
278
279 void f() override {
280 py::print("PyA.f()");
281 // This convolution just gives a `void`, but tests that PYBIND11_TYPE() works to
282 // protect a type containing a ,
283 PYBIND11_OVERRIDE(PYBIND11_TYPE(typename std::enable_if<true, void>::type), A, f);
284 }
285 };
286
287 py::class_<A, PyA>(m, "A").def(py::init<>()).def("f", &A::f);
288
289 m.def("call_f", [](A *a) { a->f(); });
290
291 // test_alias_delay_initialization2
292 // ... unless we explicitly request it, as in this example:
293 struct A2 {
294 A2() = default;
295 A2(const A2 &) = delete;
296 virtual ~A2() = default;
297 virtual void f() { py::print("A2.f()"); }
298 };
299
300 struct PyA2 : A2 {
301 PyA2() { py::print("PyA2.PyA2()"); }
302 PyA2(const PyA2 &) = delete;
303 ~PyA2() override { py::print("PyA2.~PyA2()"); }
304 void f() override {
305 py::print("PyA2.f()");
306 PYBIND11_OVERRIDE(void, A2, f);
307 }
308 };
309
310 py::class_<A2, PyA2>(m, "A2")
311 .def(py::init_alias<>())
312 .def(py::init([](int) { return new PyA2(); }))
313 .def("f", &A2::f);
314
315 m.def("call_f", [](A2 *a2) { a2->f(); });
316
317 // test_dispatch_issue
318 // #159: virtual function dispatch has problems with similar-named functions
319 py::class_<Base, DispatchIssue>(m, "DispatchIssue")
320 .def(py::init<>())
321 .def("dispatch", &Base::dispatch);
322
323 m.def("dispatch_issue_go", [](const Base *b) { return b->dispatch(); });
324
325 // test_recursive_dispatch_issue
326 // #3357: Recursive dispatch fails to find python function override
327 pybind11::class_<AdderBase, Adder>(m, "Adder")
328 .def(pybind11::init<>())
329 .def("__call__", &AdderBase::operator());
330
331 pybind11::class_<AdderBase::Data>(m, "Data").def(pybind11::init<>());
332
333 m.def("add2",
334 [](const AdderBase::Data &first,
335 const AdderBase::Data &second,
336 const AdderBase &adder,
337 const AdderBase::DataVisitor &visitor) { adder(first, second, visitor); });
338
339 m.def("add3",
340 [](const AdderBase::Data &first,
341 const AdderBase::Data &second,
342 const AdderBase::Data &third,
343 const AdderBase &adder,
344 const AdderBase::DataVisitor &visitor) {
345 adder(first, second, [&](const AdderBase::Data &first_plus_second) {
346 // NOLINTNEXTLINE(readability-suspicious-call-argument)
347 adder(first_plus_second, third, visitor);
348 });
349 });
350
351 // test_override_ref
352 // #392/397: overriding reference-returning functions
353 class OverrideTest {
354 public:
355 struct A {
356 std::string value = "hi";
357 };
358 std::string v;
359 A a;
360 explicit OverrideTest(const std::string &v) : v{v} {}
361 OverrideTest() = default;
362 OverrideTest(const OverrideTest &) = delete;
363 virtual std::string str_value() { return v; }
364 virtual std::string &str_ref() { return v; }
365 virtual A A_value() { return a; }
366 virtual A &A_ref() { return a; }
367 virtual ~OverrideTest() = default;
368 };
369
370 class PyOverrideTest : public OverrideTest {
371 public:
372 using OverrideTest::OverrideTest;
373 std::string str_value() override {
374 PYBIND11_OVERRIDE(std::string, OverrideTest, str_value);
375 }
376 // Not allowed (enabling the below should hit a static_assert failure): we can't get a
377 // reference to a python numeric value, since we only copy values in the numeric type
378 // caster:
379#ifdef PYBIND11_NEVER_DEFINED_EVER
380 std::string &str_ref() override {
381 PYBIND11_OVERRIDE(std::string &, OverrideTest, str_ref);
382 }
383#endif
384 // But we can work around it like this:
385 private:
386 std::string _tmp;
387 std::string str_ref_helper() { PYBIND11_OVERRIDE(std::string, OverrideTest, str_ref); }
388
389 public:
390 std::string &str_ref() override { return _tmp = str_ref_helper(); }
391
392 A A_value() override { PYBIND11_OVERRIDE(A, OverrideTest, A_value); }
393 A &A_ref() override { PYBIND11_OVERRIDE(A &, OverrideTest, A_ref); }
394 };
395
396 py::class_<OverrideTest::A>(m, "OverrideTest_A")
397 .def_readwrite("value", &OverrideTest::A::value);
398 py::class_<OverrideTest, PyOverrideTest>(m, "OverrideTest")
399 .def(py::init<const std::string &>())
400 .def("str_value", &OverrideTest::str_value)
401#ifdef PYBIND11_NEVER_DEFINED_EVER
402 .def("str_ref", &OverrideTest::str_ref)
403#endif
404 .def("A_value", &OverrideTest::A_value)
405 .def("A_ref", &OverrideTest::A_ref);
406
409 std::shared_ptr<test_override_cache_helper>>(m, "test_override_cache_helper")
410 .def(py::init_alias<>())
412
413 m.def("test_override_cache", test_override_cache);
414}
415
416// Inheriting virtual methods. We do two versions here: the repeat-everything version and the
417// templated trampoline versions mentioned in docs/advanced.rst.
418//
419// These base classes are exactly the same, but we technically need distinct
420// classes for this example code because we need to be able to bind them
421// properly (pybind11, sensibly, doesn't allow us to bind the same C++ class to
422// multiple python classes).
423class A_Repeat {
424#define A_METHODS \
425public: \
426 virtual int unlucky_number() = 0; \
427 virtual std::string say_something(unsigned times) { \
428 std::string s = ""; \
429 for (unsigned i = 0; i < times; ++i) \
430 s += "hi"; \
431 return s; \
432 } \
433 std::string say_everything() { \
434 return say_something(1) + " " + std::to_string(unlucky_number()); \
435 }
437 A_Repeat() = default;
438 A_Repeat(const A_Repeat &) = delete;
439 virtual ~A_Repeat() = default;
440};
441class B_Repeat : public A_Repeat {
442#define B_METHODS \
443public: \
444 int unlucky_number() override { return 13; } \
445 std::string say_something(unsigned times) override { \
446 return "B says hi " + std::to_string(times) + " times"; \
447 } \
448 virtual double lucky_number() { return 7.0; }
450};
451class C_Repeat : public B_Repeat {
452#define C_METHODS \
453public: \
454 int unlucky_number() override { return 4444; } \
455 double lucky_number() override { return 888; }
457};
458class D_Repeat : public C_Repeat {
459#define D_METHODS // Nothing overridden.
461};
462
463// Base classes for templated inheritance trampolines. Identical to the repeat-everything version:
464class A_Tpl {
465 A_METHODS;
466 A_Tpl() = default;
467 A_Tpl(const A_Tpl &) = delete;
468 virtual ~A_Tpl() = default;
469};
470class B_Tpl : public A_Tpl {
472};
473class C_Tpl : public B_Tpl {
475};
476class D_Tpl : public C_Tpl {
478};
479
480// Inheritance approach 1: each trampoline gets every virtual method (11 in total)
481class PyA_Repeat : public A_Repeat {
482public:
483 using A_Repeat::A_Repeat;
485 std::string say_something(unsigned times) override {
486 PYBIND11_OVERRIDE(std::string, A_Repeat, say_something, times);
487 }
488};
489class PyB_Repeat : public B_Repeat {
490public:
491 using B_Repeat::B_Repeat;
493 std::string say_something(unsigned times) override {
494 PYBIND11_OVERRIDE(std::string, B_Repeat, say_something, times);
495 }
496 double lucky_number() override { PYBIND11_OVERRIDE(double, B_Repeat, lucky_number, ); }
497};
498class PyC_Repeat : public C_Repeat {
499public:
500 using C_Repeat::C_Repeat;
502 std::string say_something(unsigned times) override {
503 PYBIND11_OVERRIDE(std::string, C_Repeat, say_something, times);
504 }
505 double lucky_number() override { PYBIND11_OVERRIDE(double, C_Repeat, lucky_number, ); }
506};
507class PyD_Repeat : public D_Repeat {
508public:
509 using D_Repeat::D_Repeat;
511 std::string say_something(unsigned times) override {
512 PYBIND11_OVERRIDE(std::string, D_Repeat, say_something, times);
513 }
514 double lucky_number() override { PYBIND11_OVERRIDE(double, D_Repeat, lucky_number, ); }
515};
516
517// Inheritance approach 2: templated trampoline classes.
518//
519// Advantages:
520// - we have only 2 (template) class and 4 method declarations (one per virtual method, plus one
521// for any override of a pure virtual method), versus 4 classes and 6 methods (MI) or 4 classes
522// and 11 methods (repeat).
523// - Compared to MI, we also don't have to change the non-trampoline inheritance to virtual, and
524// can properly inherit constructors.
525//
526// Disadvantage:
527// - the compiler must still generate and compile 14 different methods (more, even, than the 11
528// required for the repeat approach) instead of the 6 required for MI. (If there was no pure
529// method (or no pure method override), the number would drop down to the same 11 as the repeat
530// approach).
531template <class Base = A_Tpl>
532class PyA_Tpl : public Base {
533public:
534 using Base::Base; // Inherit constructors
536 std::string say_something(unsigned times) override {
537 PYBIND11_OVERRIDE(std::string, Base, say_something, times);
538 }
539};
540template <class Base = B_Tpl>
541class PyB_Tpl : public PyA_Tpl<Base> {
542public:
543 using PyA_Tpl<Base>::PyA_Tpl; // Inherit constructors (via PyA_Tpl's inherited constructors)
544 // NOLINTNEXTLINE(bugprone-parent-virtual-call)
546 double lucky_number() override { PYBIND11_OVERRIDE(double, Base, lucky_number, ); }
547};
548// Since C_Tpl and D_Tpl don't declare any new virtual methods, we don't actually need these
549// (we can use PyB_Tpl<C_Tpl> and PyB_Tpl<D_Tpl> for the trampoline classes instead):
550/*
551template <class Base = C_Tpl> class PyC_Tpl : public PyB_Tpl<Base> {
552public:
553 using PyB_Tpl<Base>::PyB_Tpl;
554};
555template <class Base = D_Tpl> class PyD_Tpl : public PyC_Tpl<Base> {
556public:
557 using PyC_Tpl<Base>::PyC_Tpl;
558};
559*/
560
561void initialize_inherited_virtuals(py::module_ &m) {
562 // test_inherited_virtuals
563
564 // Method 1: repeat
565 py::class_<A_Repeat, PyA_Repeat>(m, "A_Repeat")
566 .def(py::init<>())
567 .def("unlucky_number", &A_Repeat::unlucky_number)
568 .def("say_something", &A_Repeat::say_something)
569 .def("say_everything", &A_Repeat::say_everything);
570 py::class_<B_Repeat, A_Repeat, PyB_Repeat>(m, "B_Repeat")
571 .def(py::init<>())
572 .def("lucky_number", &B_Repeat::lucky_number);
573 py::class_<C_Repeat, B_Repeat, PyC_Repeat>(m, "C_Repeat").def(py::init<>());
574 py::class_<D_Repeat, C_Repeat, PyD_Repeat>(m, "D_Repeat").def(py::init<>());
575
576 // test_
577 // Method 2: Templated trampolines
578 py::class_<A_Tpl, PyA_Tpl<>>(m, "A_Tpl")
579 .def(py::init<>())
580 .def("unlucky_number", &A_Tpl::unlucky_number)
581 .def("say_something", &A_Tpl::say_something)
582 .def("say_everything", &A_Tpl::say_everything);
583 py::class_<B_Tpl, A_Tpl, PyB_Tpl<>>(m, "B_Tpl")
584 .def(py::init<>())
585 .def("lucky_number", &B_Tpl::lucky_number);
586 py::class_<C_Tpl, B_Tpl, PyB_Tpl<C_Tpl>>(m, "C_Tpl").def(py::init<>());
587 py::class_<D_Tpl, C_Tpl, PyB_Tpl<D_Tpl>>(m, "D_Tpl").def(py::init<>());
588
589 // Fix issue #1454 (crash when acquiring/releasing GIL on another thread in Python 2.7)
590 m.def("test_gil", &test_gil);
591 m.def("test_gil_from_thread", &test_gil_from_thread);
592};
A_Repeat(const A_Repeat &)=delete
virtual ~A_Repeat()=default
A_METHODS A_Repeat()=default
A_Tpl(const A_Tpl &)=delete
virtual ~A_Tpl()=default
A_Tpl()=default
const std::string str1
ExampleVirt(const ExampleVirt &e)
virtual const std::string & get_string1()
virtual const std::string * get_string2()
virtual void pure_virtual()=0
ExampleVirt(ExampleVirt &&e) noexcept
virtual int run(int value)
virtual bool run_bool()=0
const std::string str2
std::string get_value() const
Movable(const Movable &m)
Movable(int a, int b)
Movable(Movable &&m) noexcept
std::string print_movable(int a, int b)
std::string print_nc(int a, int b)
virtual NonCopyable get_noncopyable(int a, int b)
NCVirt()=default
virtual ~NCVirt()=default
virtual Movable get_movable(int a, int b)=0
NCVirt(const NCVirt &)=delete
Movable get_movable(int a, int b) override
NonCopyable get_noncopyable(int a, int b) override
std::unique_ptr< int > value
NonCopyable(int a, int b)
void operator=(NonCopyable &&)=delete
NonCopyable(const NonCopyable &)=delete
NonCopyable(NonCopyable &&o) noexcept
void operator=(const NonCopyable &)=delete
std::string get_value() const
NonCopyable()=delete
std::string say_something(unsigned times) override
int unlucky_number() override
std::string say_something(unsigned times) override
int unlucky_number() override
std::string say_something(unsigned times) override
double lucky_number() override
int unlucky_number() override
double lucky_number() override
int unlucky_number() override
int unlucky_number() override
double lucky_number() override
std::string say_something(unsigned times) override
std::string say_something(unsigned times) override
int unlucky_number() override
double lucky_number() override
void pure_virtual() override
int run(int value) override
const std::string * get_string2() override
bool run_bool() override
const std::string & get_string1() override
test_override_cache_helper()=default
test_override_cache_helper(test_override_cache_helper const &Copy)=delete
virtual ~test_override_cache_helper()=default
test_override_cache_helper & operator=(test_override_cache_helper const &Right)=delete
#define PYBIND11_TYPE(...)
Lets you pass a type containing a , through a macro parameter without needing a separate typedef,...
Definition: cast.h:1661
constexpr int first(int i)
Implementation details for constexpr functions.
Definition: common.h:795
#define PYBIND11_OVERRIDE_PURE(ret_type, cname, fn,...)
\rst Macro for pure virtual functions, this function is identical to :c:macro:PYBIND11_OVERRIDE,...
Definition: pybind11.h:2838
#define PYBIND11_OVERRIDE(ret_type, cname, fn,...)
\rst Macro to populate the virtual method in the trampoline class.
Definition: pybind11.h:2831
#define PYBIND11_OVERRIDE_PURE_NAME(ret_type, cname, name, fn,...)
\rst Macro for pure virtual functions, this function is identical to :c:macro:PYBIND11_OVERRIDE_NAME,...
Definition: pybind11.h:2799
void print_copy_created(T *inst, Values &&...values)
void print_created(T *inst, Values &&...values)
void print_destroyed(T *inst, Values &&...values)
void print_move_created(T *inst, Values &&...values)
#define TEST_SUBMODULE(name, variable)
#define C_METHODS
#define A_METHODS
static void test_gil()
static void test_gil_from_thread()
#define D_METHODS
int test_override_cache(std::shared_ptr< test_override_cache_helper > const &instance)
void initialize_inherited_virtuals(py::module_ &m)
#define B_METHODS
AdderBase()=default
AdderBase(const AdderBase &)=delete
virtual void operator()(const Data &first, const Data &second, const DataVisitor &visitor) const =0
std::function< void(const Data &)> DataVisitor
virtual ~AdderBase()=default
void operator()(const Data &first, const Data &second, const DataVisitor &visitor) const override
virtual std::string dispatch() const =0
virtual ~Base()=default
Base()=default
virtual std::string dispatch() const
Base(const Base &)=delete
std::string dispatch() const override
The 'instance' type which needs to be standard layout (need to be able to use 'offsetof')
Definition: common.h:554