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
a1d00916
Unverified
Commit
a1d00916
authored
Aug 15, 2024
by
Ralf W. Grosse-Kunstleve
Committed by
GitHub
Aug 14, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backport of
https://github.com/google/pywrapcc/pull/30034
(#5305)
parent
bd5951b6
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
98 additions
and
18 deletions
+98
-18
include/pybind11/stl.h
+74
-18
tests/test_stl.cpp
+17
-0
tests/test_stl.py
+7
-0
No files found.
include/pybind11/stl.h
View file @
a1d00916
...
@@ -11,11 +11,14 @@
...
@@ -11,11 +11,14 @@
#include "pybind11.h"
#include "pybind11.h"
#include "detail/common.h"
#include "detail/common.h"
#include "detail/descr.h"
#include "detail/type_caster_base.h"
#include <deque>
#include <deque>
#include <initializer_list>
#include <initializer_list>
#include <list>
#include <list>
#include <map>
#include <map>
#include <memory>
#include <ostream>
#include <ostream>
#include <set>
#include <set>
#include <unordered_map>
#include <unordered_map>
...
@@ -349,36 +352,65 @@ struct type_caster<std::deque<Type, Alloc>> : list_caster<std::deque<Type, Alloc
...
@@ -349,36 +352,65 @@ struct type_caster<std::deque<Type, Alloc>> : list_caster<std::deque<Type, Alloc
template
<
typename
Type
,
typename
Alloc
>
template
<
typename
Type
,
typename
Alloc
>
struct
type_caster
<
std
::
list
<
Type
,
Alloc
>>
:
list_caster
<
std
::
list
<
Type
,
Alloc
>
,
Type
>
{};
struct
type_caster
<
std
::
list
<
Type
,
Alloc
>>
:
list_caster
<
std
::
list
<
Type
,
Alloc
>
,
Type
>
{};
template
<
typename
ArrayType
,
typename
V
,
size_t
...
I
>
ArrayType
vector_to_array_impl
(
V
&&
v
,
index_sequence
<
I
...
>
)
{
return
{{
std
::
move
(
v
[
I
])...}};
}
// Based on https://en.cppreference.com/w/cpp/container/array/to_array
template
<
typename
ArrayType
,
size_t
N
,
typename
V
>
ArrayType
vector_to_array
(
V
&&
v
)
{
return
vector_to_array_impl
<
ArrayType
,
V
>
(
std
::
forward
<
V
>
(
v
),
make_index_sequence
<
N
>
{});
}
template
<
typename
ArrayType
,
typename
Value
,
bool
Resizable
,
size_t
Size
=
0
>
template
<
typename
ArrayType
,
typename
Value
,
bool
Resizable
,
size_t
Size
=
0
>
struct
array_caster
{
struct
array_caster
{
using
value_conv
=
make_caster
<
Value
>
;
using
value_conv
=
make_caster
<
Value
>
;
private
:
private
:
template
<
bool
R
=
Resizable
>
std
::
unique_ptr
<
ArrayType
>
value
;
bool
require_size
(
enable_if_t
<
R
,
size_t
>
size
)
{
if
(
value
.
size
()
!=
size
)
{
template
<
bool
R
=
Resizable
,
enable_if_t
<
R
,
int
>
=
0
>
value
.
resize
(
size
);
bool
convert_elements
(
handle
seq
,
bool
convert
)
{
auto
l
=
reinterpret_borrow
<
sequence
>
(
seq
);
value
.
reset
(
new
ArrayType
{});
// Using `resize` to preserve the behavior exactly as it was before PR #5305
// For the `resize` to work, `Value` must be default constructible.
// For `std::valarray`, this is a requirement:
// https://en.cppreference.com/w/cpp/named_req/NumericType
value
->
resize
(
l
.
size
());
size_t
ctr
=
0
;
for
(
const
auto
&
it
:
l
)
{
value_conv
conv
;
if
(
!
conv
.
load
(
it
,
convert
))
{
return
false
;
}
(
*
value
)[
ctr
++
]
=
cast_op
<
Value
&&>
(
std
::
move
(
conv
));
}
}
return
true
;
return
true
;
}
}
template
<
bool
R
=
Resizable
>
bool
require_size
(
enable_if_t
<!
R
,
size_t
>
size
)
{
return
size
==
Size
;
}
template
<
bool
R
=
Resizable
,
enable_if_t
<!
R
,
int
>
=
0
>
bool
convert_elements
(
handle
seq
,
bool
convert
)
{
bool
convert_elements
(
handle
seq
,
bool
convert
)
{
auto
l
=
reinterpret_borrow
<
sequence
>
(
seq
);
auto
l
=
reinterpret_borrow
<
sequence
>
(
seq
);
if
(
!
require_size
(
l
.
size
())
)
{
if
(
l
.
size
()
!=
Size
)
{
return
false
;
return
false
;
}
}
size_t
ctr
=
0
;
// The `temp` storage is needed to support `Value` types that are not
for
(
const
auto
&
it
:
l
)
{
// default-constructible.
// Deliberate choice: no template specializations, for simplicity, and
// because the compile time overhead for the specializations is deemed
// more significant than the runtime overhead for the `temp` storage.
std
::
vector
<
Value
>
temp
;
temp
.
reserve
(
l
.
size
());
for
(
auto
it
:
l
)
{
value_conv
conv
;
value_conv
conv
;
if
(
!
conv
.
load
(
it
,
convert
))
{
if
(
!
conv
.
load
(
it
,
convert
))
{
return
false
;
return
false
;
}
}
value
[
ctr
++
]
=
cast_op
<
Value
&&>
(
std
::
move
(
conv
));
temp
.
emplace_back
(
cast_op
<
Value
&&>
(
std
::
move
(
conv
)
));
}
}
value
.
reset
(
new
ArrayType
(
vector_to_array
<
ArrayType
,
Size
>
(
std
::
move
(
temp
))));
return
true
;
return
true
;
}
}
...
@@ -416,12 +448,36 @@ public:
...
@@ -416,12 +448,36 @@ public:
return
l
.
release
();
return
l
.
release
();
}
}
PYBIND11_TYPE_CASTER
(
ArrayType
,
// Code copied from PYBIND11_TYPE_CASTER macro.
const_name
<
Resizable
>
(
const_name
(
""
),
const_name
(
"Annotated["
))
// Intentionally preserving the behavior exactly as it was before PR #5305
+
const_name
(
"list["
)
+
value_conv
::
name
+
const_name
(
"]"
)
template
<
typename
T_
,
enable_if_t
<
std
::
is_same
<
ArrayType
,
remove_cv_t
<
T_
>>::
value
,
int
>
=
0
>
+
const_name
<
Resizable
>
(
const_name
(
""
),
static
handle
cast
(
T_
*
src
,
return_value_policy
policy
,
handle
parent
)
{
const_name
(
", FixedSize("
)
if
(
!
src
)
{
+
const_name
<
Size
>
()
+
const_name
(
")]"
)));
return
none
().
release
();
}
if
(
policy
==
return_value_policy
::
take_ownership
)
{
auto
h
=
cast
(
std
::
move
(
*
src
),
policy
,
parent
);
delete
src
;
// WARNING: Assumes `src` was allocated with `new`.
return
h
;
}
return
cast
(
*
src
,
policy
,
parent
);
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator
ArrayType
*
()
{
return
&
(
*
value
);
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator
ArrayType
&
()
{
return
*
value
;
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator
ArrayType
&&
()
&&
{
return
std
::
move
(
*
value
);
}
template
<
typename
T_
>
using
cast_op_type
=
movable_cast_op_type
<
T_
>
;
static
constexpr
auto
name
=
const_name
<
Resizable
>
(
const_name
(
""
),
const_name
(
"Annotated["
))
+
const_name
(
"list["
)
+
value_conv
::
name
+
const_name
(
"]"
)
+
const_name
<
Resizable
>
(
const_name
(
""
),
const_name
(
", FixedSize("
)
+
const_name
<
Size
>
()
+
const_name
(
")]"
));
};
};
template
<
typename
Type
,
size_t
Size
>
template
<
typename
Type
,
size_t
Size
>
...
...
tests/test_stl.cpp
View file @
a1d00916
...
@@ -201,6 +201,23 @@ TEST_SUBMODULE(stl, m) {
...
@@ -201,6 +201,23 @@ TEST_SUBMODULE(stl, m) {
m
.
def
(
"cast_array"
,
[]()
{
return
std
::
array
<
int
,
2
>
{{
1
,
2
}};
});
m
.
def
(
"cast_array"
,
[]()
{
return
std
::
array
<
int
,
2
>
{{
1
,
2
}};
});
m
.
def
(
"load_array"
,
[](
const
std
::
array
<
int
,
2
>
&
a
)
{
return
a
[
0
]
==
1
&&
a
[
1
]
==
2
;
});
m
.
def
(
"load_array"
,
[](
const
std
::
array
<
int
,
2
>
&
a
)
{
return
a
[
0
]
==
1
&&
a
[
1
]
==
2
;
});
struct
NoDefaultCtor
{
explicit
constexpr
NoDefaultCtor
(
int
val
)
:
val
{
val
}
{}
int
val
;
};
struct
NoDefaultCtorArray
{
explicit
constexpr
NoDefaultCtorArray
(
int
i
)
:
arr
{{
NoDefaultCtor
(
10
+
i
),
NoDefaultCtor
(
20
+
i
)}}
{}
std
::
array
<
NoDefaultCtor
,
2
>
arr
;
};
// test_array_no_default_ctor
py
::
class_
<
NoDefaultCtor
>
(
m
,
"NoDefaultCtor"
).
def_readonly
(
"val"
,
&
NoDefaultCtor
::
val
);
py
::
class_
<
NoDefaultCtorArray
>
(
m
,
"NoDefaultCtorArray"
)
.
def
(
py
::
init
<
int
>
())
.
def_readwrite
(
"arr"
,
&
NoDefaultCtorArray
::
arr
);
// test_valarray
// test_valarray
m
.
def
(
"cast_valarray"
,
[]()
{
return
std
::
valarray
<
int
>
{
1
,
4
,
9
};
});
m
.
def
(
"cast_valarray"
,
[]()
{
return
std
::
valarray
<
int
>
{
1
,
4
,
9
};
});
m
.
def
(
"load_valarray"
,
[](
const
std
::
valarray
<
int
>
&
v
)
{
m
.
def
(
"load_valarray"
,
[](
const
std
::
valarray
<
int
>
&
v
)
{
...
...
tests/test_stl.py
View file @
a1d00916
...
@@ -48,6 +48,13 @@ def test_array(doc):
...
@@ -48,6 +48,13 @@ def test_array(doc):
)
)
def
test_array_no_default_ctor
():
lst
=
m
.
NoDefaultCtorArray
(
3
)
assert
[
e
.
val
for
e
in
lst
.
arr
]
==
[
13
,
23
]
lst
.
arr
=
m
.
NoDefaultCtorArray
(
4
)
.
arr
assert
[
e
.
val
for
e
in
lst
.
arr
]
==
[
14
,
24
]
def
test_valarray
(
doc
):
def
test_valarray
(
doc
):
"""std::valarray <-> list"""
"""std::valarray <-> list"""
lst
=
m
.
cast_valarray
()
lst
=
m
.
cast_valarray
()
...
...
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