Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pybind11
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
pybind11
Commits
4336a7da
Commit
4336a7da
authored
Aug 21, 2017
by
Wenzel Jakob
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support for brace initialization
parent
fb276c66
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
47 additions
and
5 deletions
+47
-5
docs/advanced/classes.rst
+24
-0
include/pybind11/detail/init.h
+5
-5
tests/test_class.cpp
+11
-0
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