mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
support for brace initialization
This commit is contained in:
parent
fb276c661f
commit
4336a7da4a
@ -492,6 +492,30 @@ you could equivalently write:
|
|||||||
|
|
||||||
which will invoke the constructor in-place at the pre-allocated memory.
|
which will invoke the constructor in-place at the pre-allocated memory.
|
||||||
|
|
||||||
|
Brace initialization
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
``pybind11::init<>`` internally uses C++11 brace initialization to call the
|
||||||
|
constructor of the target class. This means that it can be used to bind
|
||||||
|
*implicit* constructors as well:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct Aggregate {
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
};
|
||||||
|
|
||||||
|
py::class_<Aggregate>(m, "Aggregate")
|
||||||
|
.def(py::init<int, const std::string &>());
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Note that brace initialization preferentially invokes constructor overloads
|
||||||
|
taking a ``std::initializer_list``. In the rare event that this causes an
|
||||||
|
issue, you can work around it by using ``py::init(...)`` with a lambda
|
||||||
|
function that constructs the new object as desired.
|
||||||
|
|
||||||
.. _classes_with_non_public_destructors:
|
.. _classes_with_non_public_destructors:
|
||||||
|
|
||||||
Non-public destructors
|
Non-public destructors
|
||||||
|
@ -172,7 +172,7 @@ template <typename... Args> struct constructor {
|
|||||||
// we really can't support that in C++, so just ignore the second __init__.
|
// we really can't support that in C++, so just ignore the second __init__.
|
||||||
if (v_h.instance_registered()) return;
|
if (v_h.instance_registered()) return;
|
||||||
|
|
||||||
construct<Class>(v_h, new Cpp<Class>(std::forward<Args>(args)...), false);
|
construct<Class>(v_h, new Cpp<Class>{std::forward<Args>(args)...}, false);
|
||||||
}, extra...);
|
}, extra...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,9 +186,9 @@ template <typename... Args> struct constructor {
|
|||||||
if (v_h.instance_registered()) return; // Ignore duplicate __init__ calls (see above)
|
if (v_h.instance_registered()) return; // Ignore duplicate __init__ calls (see above)
|
||||||
|
|
||||||
if (Py_TYPE(v_h.inst) == cl_type->type)
|
if (Py_TYPE(v_h.inst) == cl_type->type)
|
||||||
construct<Class>(v_h, new Cpp<Class>(std::forward<Args>(args)...), false);
|
construct<Class>(v_h, new Cpp<Class>{std::forward<Args>(args)...}, false);
|
||||||
else
|
else
|
||||||
construct<Class>(v_h, new Alias<Class>(std::forward<Args>(args)...), true);
|
construct<Class>(v_h, new Alias<Class>{std::forward<Args>(args)...}, true);
|
||||||
}, extra...);
|
}, extra...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ template <typename... Args> struct constructor {
|
|||||||
cl.def("__init__", [cl_type](handle self_, Args... args) {
|
cl.def("__init__", [cl_type](handle self_, Args... args) {
|
||||||
auto v_h = load_v_h(self_, cl_type);
|
auto v_h = load_v_h(self_, cl_type);
|
||||||
if (v_h.instance_registered()) return; // Ignore duplicate __init__ calls (see above)
|
if (v_h.instance_registered()) return; // Ignore duplicate __init__ calls (see above)
|
||||||
construct<Class>(v_h, new Alias<Class>(std::forward<Args>(args)...), true);
|
construct<Class>(v_h, new Alias<Class>{std::forward<Args>(args)...}, true);
|
||||||
}, extra...);
|
}, extra...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -214,7 +214,7 @@ template <typename... Args> struct alias_constructor {
|
|||||||
cl.def("__init__", [cl_type](handle self_, Args... args) {
|
cl.def("__init__", [cl_type](handle self_, Args... args) {
|
||||||
auto v_h = load_v_h(self_, cl_type);
|
auto v_h = load_v_h(self_, cl_type);
|
||||||
if (v_h.instance_registered()) return; // Ignore duplicate __init__ calls (see above)
|
if (v_h.instance_registered()) return; // Ignore duplicate __init__ calls (see above)
|
||||||
construct<Class>(v_h, new Alias<Class>(std::forward<Args>(args)...), true);
|
construct<Class>(v_h, new Alias<Class>{std::forward<Args>(args)...}, true);
|
||||||
}, extra...);
|
}, extra...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -280,6 +280,17 @@ TEST_SUBMODULE(class_, m) {
|
|||||||
#else
|
#else
|
||||||
.def("foo", static_cast<int (ProtectedB::*)() const>(&PublicistB::foo));
|
.def("foo", static_cast<int (ProtectedB::*)() const>(&PublicistB::foo));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// test_brace_initialization
|
||||||
|
struct BraceInitialization {
|
||||||
|
int field1;
|
||||||
|
std::string field2;
|
||||||
|
};
|
||||||
|
|
||||||
|
py::class_<BraceInitialization>(m, "BraceInitialization")
|
||||||
|
.def(py::init<int, const std::string &>())
|
||||||
|
.def_readwrite("field1", &BraceInitialization::field1)
|
||||||
|
.def_readwrite("field2", &BraceInitialization::field2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int N> class BreaksBase { public: virtual ~BreaksBase() = default; };
|
template <int N> class BreaksBase { public: virtual ~BreaksBase() = default; };
|
||||||
|
@ -195,3 +195,10 @@ def test_bind_protected_functions():
|
|||||||
|
|
||||||
c = C()
|
c = C()
|
||||||
assert c.foo() == 0
|
assert c.foo() == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_brace_initialization():
|
||||||
|
""" Tests that simple POD classes can be constructed using C++11 brace initialization """
|
||||||
|
a = m.BraceInitialization(123, "test")
|
||||||
|
assert a.field1 == 123
|
||||||
|
assert a.field2 == "test"
|
||||||
|
Loading…
Reference in New Issue
Block a user