Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
4336a7da
Commit
4336a7da
authored
Aug 21, 2017
by
Wenzel Jakob
Browse files
support for brace initialization
parent
fb276c66
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
47 additions
and
5 deletions
+47
-5
docs/advanced/classes.rst
docs/advanced/classes.rst
+24
-0
include/pybind11/detail/init.h
include/pybind11/detail/init.h
+5
-5
tests/test_class.cpp
tests/test_class.cpp
+11
-0
tests/test_class.py
tests/test_class.py
+7
-0
No files found.
docs/advanced/classes.rst
View file @
4336a7da
...
@@ -492,6 +492,30 @@ you could equivalently write:
...
@@ -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
...
...
include/pybind11/detail/init.h
View file @
4336a7da
...
@@ -172,7 +172,7 @@ template <typename... Args> struct constructor {
...
@@ -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 {
...
@@ -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 {
...
@@ -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 {
...
@@ -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
...);
}
}
};
};
...
...
tests/test_class.cpp
View file @
4336a7da
...
@@ -280,6 +280,17 @@ TEST_SUBMODULE(class_, m) {
...
@@ -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
;
};
...
...
tests/test_class.py
View file @
4336a7da
...
@@ -195,3 +195,10 @@ def test_bind_protected_functions():
...
@@ -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"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment