Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
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
Hide 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