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
21d01988
Commit
21d01988
authored
Feb 14, 2021
by
Ralf W. Grosse-Kunstleve
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'test_unique_ptr_member' into pr2672_use_smart_holder_as_default
parents
8627dc7e
04b05c3d
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
95 additions
and
10 deletions
+95
-10
include/pybind11/detail/init.h
+24
-10
tests/test_class_sh_factory_constructors.cpp
+37
-0
tests/test_class_sh_factory_constructors.py
+34
-0
No files found.
include/pybind11/detail/init.h
View file @
21d01988
...
...
@@ -176,13 +176,20 @@ template <typename Class, typename D = std::default_delete<Cpp<Class>>,
void
construct
(
value_and_holder
&
v_h
,
std
::
unique_ptr
<
Cpp
<
Class
>
,
D
>
&&
unq_ptr
,
bool
need_alias
)
{
auto
*
ptr
=
unq_ptr
.
get
();
no_nullptr
(
ptr
);
// If we need an alias, check that the held pointer is actually an alias instance
if
(
Class
::
has_alias
&&
need_alias
&&
!
is_alias
<
Class
>
(
ptr
))
throw
type_error
(
"pybind11::init(): construction failed: returned holder-wrapped instance "
if
(
Class
::
has_alias
&&
need_alias
)
throw
type_error
(
"pybind11::init(): construction failed: returned std::unique_ptr pointee "
"is not an alias instance"
);
auto
smhldr
=
smart_holder
::
from_unique_ptr
(
std
::
move
(
unq_ptr
));
v_h
.
value_ptr
()
=
ptr
;
v_h
.
type
->
init_instance
(
v_h
.
inst
,
&
smhldr
);
}
auto
smhldr
=
pybindit
::
memory
::
smart_holder
::
from_unique_ptr
(
std
::
move
(
unq_ptr
));
template
<
typename
Class
,
typename
D
=
std
::
default_delete
<
Alias
<
Class
>>
,
detail
::
enable_if_t
<
detail
::
is_smart_holder_type_caster
<
Alias
<
Class
>>::
value
,
int
>
=
0
>
void
construct
(
value_and_holder
&
v_h
,
std
::
unique_ptr
<
Alias
<
Class
>
,
D
>
&&
unq_ptr
,
bool
/*need_alias*/
)
{
auto
*
ptr
=
unq_ptr
.
get
();
no_nullptr
(
ptr
);
auto
smhldr
=
smart_holder
::
from_unique_ptr
(
std
::
move
(
unq_ptr
));
v_h
.
value_ptr
()
=
ptr
;
v_h
.
type
->
init_instance
(
v_h
.
inst
,
&
smhldr
);
}
...
...
@@ -192,13 +199,20 @@ template <typename Class,
void
construct
(
value_and_holder
&
v_h
,
std
::
shared_ptr
<
Cpp
<
Class
>>
&&
shd_ptr
,
bool
need_alias
)
{
auto
*
ptr
=
shd_ptr
.
get
();
no_nullptr
(
ptr
);
// If we need an alias, check that the held pointer is actually an alias instance
if
(
Class
::
has_alias
&&
need_alias
&&
!
is_alias
<
Class
>
(
ptr
))
throw
type_error
(
"pybind11::init(): construction failed: returned holder-wrapped instance "
if
(
Class
::
has_alias
&&
need_alias
)
throw
type_error
(
"pybind11::init(): construction failed: returned std::shared_ptr pointee "
"is not an alias instance"
);
auto
smhldr
=
smart_holder
::
from_shared_ptr
(
std
::
move
(
shd_ptr
));
v_h
.
value_ptr
()
=
ptr
;
v_h
.
type
->
init_instance
(
v_h
.
inst
,
&
smhldr
);
}
auto
smhldr
=
pybindit
::
memory
::
smart_holder
::
from_shared_ptr
(
std
::
move
(
shd_ptr
));
template
<
typename
Class
,
detail
::
enable_if_t
<
detail
::
is_smart_holder_type_caster
<
Alias
<
Class
>>::
value
,
int
>
=
0
>
void
construct
(
value_and_holder
&
v_h
,
std
::
shared_ptr
<
Alias
<
Class
>>
&&
shd_ptr
,
bool
/*need_alias*/
)
{
auto
*
ptr
=
shd_ptr
.
get
();
no_nullptr
(
ptr
);
auto
smhldr
=
smart_holder
::
from_shared_ptr
(
std
::
move
(
shd_ptr
));
v_h
.
value_ptr
()
=
ptr
;
v_h
.
type
->
init_instance
(
v_h
.
inst
,
&
smhldr
);
}
...
...
tests/test_class_sh_factory_constructors.cpp
View file @
21d01988
...
...
@@ -54,6 +54,15 @@ std::unique_ptr<atyp_udcp const, sddc> rtrn_udcp() { return std::unique_ptr<atyp
// clang-format on
// Minimalistic approach to achieve full coverage of construct() overloads for constructing
// smart_holder from unique_ptr and shared_ptr returns.
struct
with_alias
{
int
val
=
0
;
virtual
~
with_alias
()
=
default
;
};
struct
with_alias_alias
:
with_alias
{};
struct
sddwaa
:
std
::
default_delete
<
with_alias_alias
>
{};
}
// namespace test_class_sh_factory_constructors
}
// namespace pybind11_tests
...
...
@@ -69,6 +78,7 @@ PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::test_class_sh_factory_constru
PYBIND11_SMART_HOLDER_TYPE_CASTERS
(
pybind11_tests
::
test_class_sh_factory_constructors
::
atyp_uqcp
)
PYBIND11_SMART_HOLDER_TYPE_CASTERS
(
pybind11_tests
::
test_class_sh_factory_constructors
::
atyp_udmp
)
PYBIND11_SMART_HOLDER_TYPE_CASTERS
(
pybind11_tests
::
test_class_sh_factory_constructors
::
atyp_udcp
)
PYBIND11_SMART_HOLDER_TYPE_CASTERS
(
pybind11_tests
::
test_class_sh_factory_constructors
::
with_alias
)
TEST_SUBMODULE
(
class_sh_factory_constructors
,
m
)
{
using
namespace
pybind11_tests
::
test_class_sh_factory_constructors
;
...
...
@@ -134,4 +144,31 @@ TEST_SUBMODULE(class_sh_factory_constructors, m) {
// classh: ... cannot pass object of non-trivial type ...
// .def(py::init(&rtrn_udcp))
.
def
(
"get_mtxt"
,
get_mtxt
<
atyp_udcp
>
);
py
::
classh
<
with_alias
,
with_alias_alias
>
(
m
,
"with_alias"
)
.
def_readonly
(
"val"
,
&
with_alias
::
val
)
.
def
(
py
::
init
([](
int
i
)
{
auto
p
=
std
::
unique_ptr
<
with_alias_alias
,
sddwaa
>
(
new
with_alias_alias
);
p
->
val
=
i
*
100
;
return
p
;
}))
.
def
(
py
::
init
([](
int
i
,
int
j
)
{
auto
p
=
std
::
unique_ptr
<
with_alias_alias
>
(
new
with_alias_alias
);
p
->
val
=
i
*
100
+
j
*
10
;
return
p
;
}))
.
def
(
py
::
init
([](
int
i
,
int
j
,
int
k
)
{
auto
p
=
std
::
shared_ptr
<
with_alias_alias
>
(
new
with_alias_alias
);
p
->
val
=
i
*
100
+
j
*
10
+
k
;
return
p
;
}))
.
def
(
py
::
init
(
[](
int
,
int
,
int
,
int
)
{
return
std
::
unique_ptr
<
with_alias
>
(
new
with_alias
);
},
[](
int
,
int
,
int
,
int
)
{
return
std
::
unique_ptr
<
with_alias
>
(
new
with_alias
);
// Invalid alias factory.
}))
.
def
(
py
::
init
([](
int
,
int
,
int
,
int
,
int
)
{
return
std
::
make_shared
<
with_alias
>
();
},
[](
int
,
int
,
int
,
int
,
int
)
{
return
std
::
make_shared
<
with_alias
>
();
// Invalid alias factory.
}));
}
tests/test_class_sh_factory_constructors.py
View file @
21d01988
# -*- coding: utf-8 -*-
import
pytest
from
pybind11_tests
import
class_sh_factory_constructors
as
m
...
...
@@ -16,3 +17,36 @@ def test_atyp_factories():
# sert m.atyp_uqcp().get_mtxt() == "Uqcp"
assert
m
.
atyp_udmp
()
.
get_mtxt
()
==
"Udmp"
# sert m.atyp_udcp().get_mtxt() == "Udcp"
@pytest.mark.parametrize
(
"init_args, expected"
,
[
((
3
,),
300
),
((
5
,
7
),
570
),
((
9
,
11
,
13
),
1023
),
],
)
def
test_with_alias_success
(
init_args
,
expected
):
assert
m
.
with_alias
(
*
init_args
)
.
val
==
expected
@pytest.mark.parametrize
(
"num_init_args, smart_ptr"
,
[
(
4
,
"std::unique_ptr"
),
(
5
,
"std::shared_ptr"
),
],
)
def
test_with_alias_invalid
(
num_init_args
,
smart_ptr
):
class
PyDrvdWithAlias
(
m
.
with_alias
):
pass
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
PyDrvdWithAlias
(
*
((
0
,)
*
num_init_args
))
assert
(
str
(
excinfo
.
value
)
==
"pybind11::init(): construction failed: returned "
+
smart_ptr
+
" pointee is not an alias instance"
)
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