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
d922dffe
Commit
d922dffe
authored
Sep 19, 2016
by
Wenzel Jakob
Committed by
GitHub
Sep 19, 2016
Browse files
Merge pull request #410 from wjakob/mi
WIP: Multiple inheritance support
parents
7962f30d
e72a676b
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
364 additions
and
178 deletions
+364
-178
README.md
README.md
+3
-1
docs/advanced.rst
docs/advanced.rst
+44
-0
docs/classes.rst
docs/classes.rst
+5
-11
docs/intro.rst
docs/intro.rst
+4
-2
docs/limitations.rst
docs/limitations.rst
+4
-7
include/pybind11/attr.h
include/pybind11/attr.h
+45
-16
include/pybind11/cast.h
include/pybind11/cast.h
+146
-52
include/pybind11/common.h
include/pybind11/common.h
+13
-2
include/pybind11/descr.h
include/pybind11/descr.h
+4
-4
include/pybind11/eigen.h
include/pybind11/eigen.h
+10
-10
include/pybind11/numpy.h
include/pybind11/numpy.h
+8
-8
include/pybind11/operators.h
include/pybind11/operators.h
+0
-1
include/pybind11/pybind11.h
include/pybind11/pybind11.h
+59
-42
include/pybind11/pytypes.h
include/pybind11/pytypes.h
+5
-7
include/pybind11/stl.h
include/pybind11/stl.h
+1
-1
include/pybind11/stl_bind.h
include/pybind11/stl_bind.h
+7
-9
tests/CMakeLists.txt
tests/CMakeLists.txt
+1
-1
tests/test_callbacks.py
tests/test_callbacks.py
+1
-1
tests/test_inheritance.cpp
tests/test_inheritance.cpp
+1
-1
tests/test_inheritance.py
tests/test_inheritance.py
+3
-2
No files found.
README.md
View file @
d922dffe
...
@@ -45,10 +45,12 @@ pybind11 can map the following core C++ features to Python
...
@@ -45,10 +45,12 @@ pybind11 can map the following core C++ features to Python
-
Arbitrary exception types
-
Arbitrary exception types
-
Enumerations
-
Enumerations
-
Callbacks
-
Callbacks
-
Iterators and ranges
-
Custom operators
-
Custom operators
-
Single and multiple inheritance
-
STL data structures
-
STL data structures
-
Iterators and ranges
-
Iterators and ranges
-
Smart pointers with reference counting like
`std::shared_ptr`
-
Smart pointers with reference counting like
`
`std::shared_ptr`
`
-
Internal references with correct reference counting
-
Internal references with correct reference counting
-
C++ classes with virtual (and pure virtual) methods can be extended in Python
-
C++ classes with virtual (and pure virtual) methods can be extended in Python
...
...
docs/advanced.rst
View file @
d922dffe
...
@@ -217,6 +217,8 @@ The following interactive session shows how to call them from Python.
...
@@ -217,6 +217,8 @@ The following interactive session shows how to call them from Python.
that demonstrates how to work with callbacks and anonymous functions in
that demonstrates how to work with callbacks and anonymous functions in
more detail.
more detail.
.. _overriding_virtuals:
Overriding virtual functions in Python
Overriding virtual functions in Python
======================================
======================================
...
@@ -2151,3 +2153,45 @@ type is explicitly allowed.
...
@@ -2151,3 +2153,45 @@ type is explicitly allowed.
};
};
}
}
};
};
Multiple Inheritance
====================
pybind11 can create bindings for types that derive from multiple base types
(aka. *multiple inheritance*). To do so, specify all bases in the template
arguments of the ``class_`` declaration:
.. code-block:: cpp
py::class_<MyType, BaseType1, BaseType2, BaseType3>(m, "MyType")
...
The base types can be specified in arbitrary order, and they can even be
interspersed with alias types and holder types (discussed earlier in this
document)---pybind11 will automatically find out which is which. The only
requirement is that the first template argument is the type to be declared.
There are two caveats regarding the implementation of this feature:
1. When only one base type is specified for a C++ type that actually has
multiple bases, pybind11 will assume that it does not participate in
multiple inheritance, which can lead to undefined behavior. In such cases,
add the tag ``multiple_inheritance``:
.. code-block:: cpp
py::class_<MyType, BaseType2>(m, "MyType", py::multiple_inheritance());
The tag is redundant and does not need to be specified when multiple base
types are listed.
2. As was previously discussed in the section on :ref:`overriding_virtuals`, it
is easy to create Python types that derive from C++ classes. It is even
possible to make use of multiple inheritance to declare a Python class which
has e.g. a C++ and a Python class as bases. However, any attempt to create a
type that has *two or more* C++ classes in its hierarchy of base types will
fail with a fatal error message: ``TypeError: multiple bases have instance
lay-out conflict``. Core Python types that are implemented in C (e.g.
``dict``, ``list``, ``Exception``, etc.) also fall under this combination
and cannot be combined with C++ types bound using pybind11 via multiple
inheritance.
docs/classes.rst
View file @
d922dffe
...
@@ -185,10 +185,9 @@ inheritance relationship:
...
@@ -185,10 +185,9 @@ inheritance relationship:
std::string bark() const { return "woof!"; }
std::string bark() const { return "woof!"; }
};
};
There are t
hree
different ways of indicating a hierarchical relationship to
There are t
wo
different ways of indicating a hierarchical relationship to
pybind11: the first specifies the C++ base class as an extra template
pybind11: the first specifies the C++ base class as an extra template
parameter of the :class:`class_`; the second uses a special ``base`` attribute
parameter of the :class:`class_`:
passed into the constructor:
.. code-block:: cpp
.. code-block:: cpp
...
@@ -201,11 +200,6 @@ passed into the constructor:
...
@@ -201,11 +200,6 @@ passed into the constructor:
.def(py::init<const std::string &>())
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
.def("bark", &Dog::bark);
// Method 2: py::base attribute:
py::class_<Dog>(m, "Dog", py::base<Pet>() /* <- specify C++ parent type */)
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
Alternatively, we can also assign a name to the previously bound ``Pet``
Alternatively, we can also assign a name to the previously bound ``Pet``
:class:`class_` object and reference it when binding the ``Dog`` class:
:class:`class_` object and reference it when binding the ``Dog`` class:
...
@@ -215,13 +209,13 @@ Alternatively, we can also assign a name to the previously bound ``Pet``
...
@@ -215,13 +209,13 @@ Alternatively, we can also assign a name to the previously bound ``Pet``
pet.def(py::init<const std::string &>())
pet.def(py::init<const std::string &>())
.def_readwrite("name", &Pet::name);
.def_readwrite("name", &Pet::name);
// Method
3
: pass parent class_ object:
// Method
2
: pass parent class_ object:
py::class_<Dog>(m, "Dog", pet /* <- specify Python parent type */)
py::class_<Dog>(m, "Dog", pet /* <- specify Python parent type */)
.def(py::init<const std::string &>())
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
.def("bark", &Dog::bark);
Functionality-wise,
all three
approaches are
completely
equivalent. Afterwards,
Functionality-wise,
both
approaches are equivalent. Afterwards,
instances will
instances will
expose fields and methods of both types:
expose fields and methods of both types:
.. code-block:: pycon
.. code-block:: pycon
...
...
docs/intro.rst
View file @
d922dffe
...
@@ -35,12 +35,14 @@ The following core C++ features can be mapped to Python
...
@@ -35,12 +35,14 @@ The following core C++ features can be mapped to Python
- Instance methods and static methods
- Instance methods and static methods
- Overloaded functions
- Overloaded functions
- Instance attributes and static attributes
- Instance attributes and static attributes
-
E
xceptions
-
Arbitrary e
xception
type
s
- Enumerations
- Enumerations
- Iterators and ranges
- Callbacks
- Callbacks
- Iterators and ranges
- Custom operators
- Custom operators
- Single and multiple inheritance
- STL data structures
- STL data structures
- Iterators and ranges
- Smart pointers with reference counting like ``std::shared_ptr``
- Smart pointers with reference counting like ``std::shared_ptr``
- Internal references with correct reference counting
- Internal references with correct reference counting
- C++ classes with virtual (and pure virtual) methods can be extended in Python
- C++ classes with virtual (and pure virtual) methods can be extended in Python
...
...
docs/limitations.rst
View file @
d922dffe
...
@@ -9,15 +9,12 @@ certain limitations:
...
@@ -9,15 +9,12 @@ certain limitations:
values. This means that some additional care is needed to avoid bugs that
values. This means that some additional care is needed to avoid bugs that
would be caught by the type checker in a traditional C++ program.
would be caught by the type checker in a traditional C++ program.
- Multiple inheritance relationships on the C++ side cannot be mapped to
Python.
- The NumPy interface ``pybind11::array`` greatly simplifies accessing
- The NumPy interface ``pybind11::array`` greatly simplifies accessing
numerical data from C++ (and vice versa), but it's not a full-blown array
numerical data from C++ (and vice versa), but it's not a full-blown array
class like ``Eigen::Array`` or ``boost.multi_array``.
class like ``Eigen::Array`` or ``boost.multi_array``.
All of t
hese features could be implemented but would lead to a significant
T
hese features could be implemented but would lead to a significant
increase in
increase in
complexity. I've decided to draw the line here to keep this project
complexity. I've decided to draw the line here to keep this project
simple and
simple and
compact. Users who absolutely require these features are encouraged
compact. Users who absolutely require these features are encouraged
to fork
to fork
pybind11.
pybind11.
include/pybind11/attr.h
View file @
d922dffe
...
@@ -33,11 +33,17 @@ struct name { const char *value; name(const char *value) : value(value) { } };
...
@@ -33,11 +33,17 @@ struct name { const char *value; name(const char *value) : value(value) { } };
struct
sibling
{
handle
value
;
sibling
(
const
handle
&
value
)
:
value
(
value
.
ptr
())
{
}
};
struct
sibling
{
handle
value
;
sibling
(
const
handle
&
value
)
:
value
(
value
.
ptr
())
{
}
};
/// Annotation indicating that a class derives from another given type
/// Annotation indicating that a class derives from another given type
template
<
typename
T
>
struct
base
{
};
template
<
typename
T
>
struct
base
{
PYBIND11_DEPRECATED
(
"base<T>() was deprecated in favor of specifying 'T' as a template argument to class_"
)
base
()
{
}
};
/// Keep patient alive while nurse lives
/// Keep patient alive while nurse lives
template
<
int
Nurse
,
int
Patient
>
struct
keep_alive
{
};
template
<
int
Nurse
,
int
Patient
>
struct
keep_alive
{
};
/// Annotation indicating that a class is involved in a multiple inheritance relationship
struct
multiple_inheritance
{
};
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
/* Forward declarations */
/* Forward declarations */
enum
op_id
:
int
;
enum
op_id
:
int
;
...
@@ -124,6 +130,8 @@ struct function_record {
...
@@ -124,6 +130,8 @@ struct function_record {
/// Special data structure which (temporarily) holds metadata about a bound class
/// Special data structure which (temporarily) holds metadata about a bound class
struct
type_record
{
struct
type_record
{
PYBIND11_NOINLINE
type_record
()
{
}
/// Handle to the parent scope
/// Handle to the parent scope
handle
scope
;
handle
scope
;
...
@@ -145,21 +153,36 @@ struct type_record {
...
@@ -145,21 +153,36 @@ struct type_record {
/// Function pointer to class_<..>::dealloc
/// Function pointer to class_<..>::dealloc
void
(
*
dealloc
)(
PyObject
*
)
=
nullptr
;
void
(
*
dealloc
)(
PyObject
*
)
=
nullptr
;
// Pointer to RTTI type_info data structure of base class
/// List of base classes of the newly created type
const
std
::
type_info
*
base_type
=
nullptr
;
list
bases
;
/// OR: Python handle to base class
handle
base_handle
;
/// Optional docstring
/// Optional docstring
const
char
*
doc
=
nullptr
;
const
char
*
doc
=
nullptr
;
/// Multiple inheritance marker
bool
multiple_inheritance
=
false
;
PYBIND11_NOINLINE
void
add_base
(
const
std
::
type_info
*
base
,
void
*
(
*
caster
)(
void
*
))
{
auto
base_info
=
detail
::
get_type_info
(
*
base
,
false
);
if
(
!
base_info
)
{
std
::
string
tname
(
base
->
name
());
detail
::
clean_type_id
(
tname
);
pybind11_fail
(
"generic_type: type
\"
"
+
std
::
string
(
name
)
+
"
\"
referenced unknown base type
\"
"
+
tname
+
"
\"
"
);
}
bases
.
append
((
PyObject
*
)
base_info
->
type
);
if
(
caster
)
base_info
->
implicit_casts
.
push_back
(
std
::
make_pair
(
type
,
caster
));
}
};
};
/**
/**
* Partial template specializations to process custom attributes provided to
* Partial template specializations to process custom attributes provided to
* cpp_function_ and class_. These are either used to initialize the respective
* cpp_function_ and class_. These are either used to initialize the respective
* fields in the type_record and function_record data structures or executed
* fields in the type_record and function_record data structures or executed
at
*
at
runtime to deal with custom call policies (e.g. keep_alive).
* runtime to deal with custom call policies (e.g. keep_alive).
*/
*/
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
process_attribute
;
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
process_attribute
;
...
@@ -253,14 +276,20 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
...
@@ -253,14 +276,20 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
/// Process a parent class attribute
/// Process a parent class attribute
template
<
typename
T
>
template
<
typename
T
>
struct
process_attribute
<
T
,
typename
std
::
enable_if
<
std
::
is_base_of
<
handle
,
T
>::
value
>
::
type
>
:
process_attribute_default
<
handle
>
{
struct
process_attribute
<
T
,
enable_if
_t
<
std
::
is_base_of
<
handle
,
T
>::
value
>>
:
process_attribute_default
<
handle
>
{
static
void
init
(
const
handle
&
h
,
type_record
*
r
)
{
r
->
base
_handle
=
h
;
}
static
void
init
(
const
handle
&
h
,
type_record
*
r
)
{
r
->
base
s
.
append
(
h
)
;
}
};
};
/// Process a parent class attribute
/// Process a parent class attribute
(deprecated, does not support multiple inheritance)
template
<
typename
T
>
template
<
typename
T
>
struct
process_attribute
<
base
<
T
>>
:
process_attribute_default
<
base
<
T
>>
{
struct
process_attribute
<
base
<
T
>>
:
process_attribute_default
<
base
<
T
>>
{
static
void
init
(
const
base
<
T
>
&
,
type_record
*
r
)
{
r
->
base_type
=
&
typeid
(
T
);
}
static
void
init
(
const
base
<
T
>
&
,
type_record
*
r
)
{
r
->
add_base
(
&
typeid
(
T
),
nullptr
);
}
};
/// Process a multiple inheritance attribute
template
<
>
struct
process_attribute
<
multiple_inheritance
>
:
process_attribute_default
<
multiple_inheritance
>
{
static
void
init
(
const
multiple_inheritance
&
,
type_record
*
r
)
{
r
->
multiple_inheritance
=
true
;
}
};
};
/***
/***
...
@@ -269,13 +298,13 @@ struct process_attribute<base<T>> : process_attribute_default<base<T>> {
...
@@ -269,13 +298,13 @@ struct process_attribute<base<T>> : process_attribute_default<base<T>> {
* otherwise
* otherwise
*/
*/
template
<
int
Nurse
,
int
Patient
>
struct
process_attribute
<
keep_alive
<
Nurse
,
Patient
>>
:
public
process_attribute_default
<
keep_alive
<
Nurse
,
Patient
>>
{
template
<
int
Nurse
,
int
Patient
>
struct
process_attribute
<
keep_alive
<
Nurse
,
Patient
>>
:
public
process_attribute_default
<
keep_alive
<
Nurse
,
Patient
>>
{
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
typename
std
::
enable_if
<
N
!=
0
&&
P
!=
0
,
int
>
::
type
=
0
>
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
enable_if
_t
<
N
!=
0
&&
P
!=
0
,
int
>
=
0
>
static
void
precall
(
handle
args
)
{
keep_alive_impl
(
Nurse
,
Patient
,
args
,
handle
());
}
static
void
precall
(
handle
args
)
{
keep_alive_impl
(
Nurse
,
Patient
,
args
,
handle
());
}
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
typename
std
::
enable_if
<
N
!=
0
&&
P
!=
0
,
int
>
::
type
=
0
>
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
enable_if
_t
<
N
!=
0
&&
P
!=
0
,
int
>
=
0
>
static
void
postcall
(
handle
,
handle
)
{
}
static
void
postcall
(
handle
,
handle
)
{
}
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
typename
std
::
enable_if
<
N
==
0
||
P
==
0
,
int
>
::
type
=
0
>
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
enable_if
_t
<
N
==
0
||
P
==
0
,
int
>
=
0
>
static
void
precall
(
handle
)
{
}
static
void
precall
(
handle
)
{
}
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
typename
std
::
enable_if
<
N
==
0
||
P
==
0
,
int
>
::
type
=
0
>
template
<
int
N
=
Nurse
,
int
P
=
Patient
,
enable_if
_t
<
N
==
0
||
P
==
0
,
int
>
=
0
>
static
void
postcall
(
handle
args
,
handle
ret
)
{
keep_alive_impl
(
Nurse
,
Patient
,
args
,
ret
);
}
static
void
postcall
(
handle
args
,
handle
ret
)
{
keep_alive_impl
(
Nurse
,
Patient
,
args
,
ret
);
}
};
};
...
...
include/pybind11/cast.h
View file @
d922dffe
...
@@ -15,7 +15,6 @@
...
@@ -15,7 +15,6 @@
#include "descr.h"
#include "descr.h"
#include <array>
#include <array>
#include <limits>
#include <limits>
#include <iostream>
NAMESPACE_BEGIN
(
pybind11
)
NAMESPACE_BEGIN
(
pybind11
)
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
...
@@ -25,9 +24,13 @@ struct type_info {
...
@@ -25,9 +24,13 @@ struct type_info {
PyTypeObject
*
type
;
PyTypeObject
*
type
;
size_t
type_size
;
size_t
type_size
;
void
(
*
init_holder
)(
PyObject
*
,
const
void
*
);
void
(
*
init_holder
)(
PyObject
*
,
const
void
*
);
std
::
vector
<
PyObject
*
(
*
)(
PyObject
*
,
PyTypeObject
*
)
>
implicit_conversions
;
std
::
vector
<
PyObject
*
(
*
)(
PyObject
*
,
PyTypeObject
*
)
>
implicit_conversions
;
std
::
vector
<
std
::
pair
<
const
std
::
type_info
*
,
void
*
(
*
)(
void
*
)
>>
implicit_casts
;
buffer_info
*
(
*
get_buffer
)(
PyObject
*
,
void
*
)
=
nullptr
;
buffer_info
*
(
*
get_buffer
)(
PyObject
*
,
void
*
)
=
nullptr
;
void
*
get_buffer_data
=
nullptr
;
void
*
get_buffer_data
=
nullptr
;
/** A simple type never occurs as a (direct or indirect) parent
* of a class that makes use of multiple inheritance */
bool
simple_type
=
true
;
};
};
PYBIND11_NOINLINE
inline
internals
&
get_internals
()
{
PYBIND11_NOINLINE
inline
internals
&
get_internals
()
{
...
@@ -72,32 +75,34 @@ PYBIND11_NOINLINE inline internals &get_internals() {
...
@@ -72,32 +75,34 @@ PYBIND11_NOINLINE inline internals &get_internals() {
return
*
internals_ptr
;
return
*
internals_ptr
;
}
}
PYBIND11_NOINLINE
inline
detail
::
type_info
*
get_type_info
(
PyTypeObject
*
type
,
bool
throw_if_missing
=
true
)
{
PYBIND11_NOINLINE
inline
detail
::
type_info
*
get_type_info
(
PyTypeObject
*
type
)
{
auto
const
&
type_dict
=
get_internals
().
registered_types_py
;
auto
const
&
type_dict
=
get_internals
().
registered_types_py
;
do
{
do
{
auto
it
=
type_dict
.
find
(
type
);
auto
it
=
type_dict
.
find
(
type
);
if
(
it
!=
type_dict
.
end
())
if
(
it
!=
type_dict
.
end
())
return
(
detail
::
type_info
*
)
it
->
second
;
return
(
detail
::
type_info
*
)
it
->
second
;
type
=
type
->
tp_base
;
type
=
type
->
tp_base
;
if
(
!
type
)
{
if
(
!
type
)
if
(
throw_if_missing
)
pybind11_fail
(
"pybind11::detail::get_type_info: unable to find type object!"
);
return
nullptr
;
return
nullptr
;
}
}
while
(
true
);
}
while
(
true
);
}
}
PYBIND11_NOINLINE
inline
detail
::
type_info
*
get_type_info
(
const
std
::
type_info
&
tp
)
{
PYBIND11_NOINLINE
inline
detail
::
type_info
*
get_type_info
(
const
std
::
type_info
&
tp
,
bool
throw_if_missing
)
{
auto
&
types
=
get_internals
().
registered_types_cpp
;
auto
&
types
=
get_internals
().
registered_types_cpp
;
auto
it
=
types
.
find
(
std
::
type_index
(
tp
));
auto
it
=
types
.
find
(
std
::
type_index
(
tp
));
if
(
it
!=
types
.
end
())
if
(
it
!=
types
.
end
())
return
(
detail
::
type_info
*
)
it
->
second
;
return
(
detail
::
type_info
*
)
it
->
second
;
if
(
throw_if_missing
)
{
std
::
string
tname
=
tp
.
name
();
detail
::
clean_type_id
(
tname
);
pybind11_fail
(
"pybind11::detail::get_type_info: unable to find type info for
\"
"
+
tname
+
"
\"
"
);
}
return
nullptr
;
return
nullptr
;
}
}
PYBIND11_NOINLINE
inline
handle
get_type_handle
(
const
std
::
type_info
&
tp
)
{
PYBIND11_NOINLINE
inline
handle
get_type_handle
(
const
std
::
type_info
&
tp
,
bool
throw_if_missing
)
{
detail
::
type_info
*
type_info
=
get_type_info
(
tp
);
detail
::
type_info
*
type_info
=
get_type_info
(
tp
,
throw_if_missing
);
return
handle
(
type_info
?
((
PyObject
*
)
type_info
->
type
)
:
nullptr
);
return
handle
(
type_info
?
((
PyObject
*
)
type_info
->
type
)
:
nullptr
);
}
}
...
@@ -124,7 +129,7 @@ PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr, const detail:
...
@@ -124,7 +129,7 @@ PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr, const detail:
auto
&
instances
=
get_internals
().
registered_instances
;
auto
&
instances
=
get_internals
().
registered_instances
;
auto
range
=
instances
.
equal_range
(
ptr
);
auto
range
=
instances
.
equal_range
(
ptr
);
for
(
auto
it
=
range
.
first
;
it
!=
range
.
second
;
++
it
)
{
for
(
auto
it
=
range
.
first
;
it
!=
range
.
second
;
++
it
)
{
auto
instance_type
=
detail
::
get_type_info
(
Py_TYPE
(
it
->
second
)
,
false
);
auto
instance_type
=
detail
::
get_type_info
(
Py_TYPE
(
it
->
second
));
if
(
instance_type
&&
instance_type
==
type
)
if
(
instance_type
&&
instance_type
==
type
)
return
handle
((
PyObject
*
)
it
->
second
);
return
handle
((
PyObject
*
)
it
->
second
);
}
}
...
@@ -149,18 +154,56 @@ inline void keep_alive_impl(handle nurse, handle patient);
...
@@ -149,18 +154,56 @@ inline void keep_alive_impl(handle nurse, handle patient);
class
type_caster_generic
{
class
type_caster_generic
{
public:
public:
PYBIND11_NOINLINE
type_caster_generic
(
const
std
::
type_info
&
type_info
)
PYBIND11_NOINLINE
type_caster_generic
(
const
std
::
type_info
&
type_info
)
:
typeinfo
(
get_type_info
(
type_info
))
{
}
:
typeinfo
(
get_type_info
(
type_info
,
false
))
{
}
PYBIND11_NOINLINE
bool
load
(
handle
src
,
bool
convert
)
{
PYBIND11_NOINLINE
bool
load
(
handle
src
,
bool
convert
)
{
return
load
(
src
,
convert
,
Py_TYPE
(
src
.
ptr
()));
}
bool
load
(
handle
src
,
bool
convert
,
PyTypeObject
*
tobj
)
{
if
(
!
src
||
!
typeinfo
)
if
(
!
src
||
!
typeinfo
)
return
false
;
return
false
;
if
(
src
.
is_none
())
{
if
(
src
.
is_none
())
{
value
=
nullptr
;
value
=
nullptr
;
return
true
;
return
true
;
}
else
if
(
PyType_IsSubtype
(
Py_TYPE
(
src
.
ptr
()),
typeinfo
->
type
))
{
value
=
((
instance
<
void
>
*
)
src
.
ptr
())
->
value
;
return
true
;
}
}
if
(
typeinfo
->
simple_type
)
{
/* Case 1: no multiple inheritance etc. involved */
/* Check if we can safely perform a reinterpret-style cast */
if
(
PyType_IsSubtype
(
tobj
,
typeinfo
->
type
))
{
value
=
reinterpret_cast
<
instance
<
void
>
*>
(
src
.
ptr
())
->
value
;
return
true
;
}
}
else
{
/* Case 2: multiple inheritance */
/* Check if we can safely perform a reinterpret-style cast */
if
(
tobj
==
typeinfo
->
type
)
{
value
=
reinterpret_cast
<
instance
<
void
>
*>
(
src
.
ptr
())
->
value
;
return
true
;
}
/* If this is a python class, also check the parents recursively */
auto
const
&
type_dict
=
get_internals
().
registered_types_py
;
bool
new_style_class
=
PyType_Check
(
tobj
);
if
(
type_dict
.
find
(
tobj
)
==
type_dict
.
end
()
&&
new_style_class
&&
tobj
->
tp_bases
)
{
tuple
parents
(
tobj
->
tp_bases
,
true
);
for
(
handle
parent
:
parents
)
{
bool
result
=
load
(
src
,
convert
,
(
PyTypeObject
*
)
parent
.
ptr
());
if
(
result
)
return
true
;
}
}
/* Try implicit casts */
for
(
auto
&
cast
:
typeinfo
->
implicit_casts
)
{
type_caster_generic
sub_caster
(
*
cast
.
first
);
if
(
sub_caster
.
load
(
src
,
convert
))
{
value
=
cast
.
second
(
sub_caster
.
value
);
return
true
;
}
}
}
/* Perform an implicit conversion */
if
(
convert
)
{
if
(
convert
)
{
for
(
auto
&
converter
:
typeinfo
->
implicit_conversions
)
{
for
(
auto
&
converter
:
typeinfo
->
implicit_conversions
)
{
temp
=
object
(
converter
(
src
.
ptr
(),
typeinfo
->
type
),
false
);
temp
=
object
(
converter
(
src
.
ptr
(),
typeinfo
->
type
),
false
);
...
@@ -201,7 +244,7 @@ public:
...
@@ -201,7 +244,7 @@ public:
auto
it_instances
=
internals
.
registered_instances
.
equal_range
(
src
);
auto
it_instances
=
internals
.
registered_instances
.
equal_range
(
src
);
for
(
auto
it_i
=
it_instances
.
first
;
it_i
!=
it_instances
.
second
;
++
it_i
)
{
for
(
auto
it_i
=
it_instances
.
first
;
it_i
!=
it_instances
.
second
;
++
it_i
)
{
auto
instance_type
=
detail
::
get_type_info
(
Py_TYPE
(
it_i
->
second
)
,
false
);
auto
instance_type
=
detail
::
get_type_info
(
Py_TYPE
(
it_i
->
second
));
if
(
instance_type
&&
instance_type
==
tinfo
)
if
(
instance_type
&&
instance_type
==
tinfo
)
return
handle
((
PyObject
*
)
it_i
->
second
).
inc_ref
();
return
handle
((
PyObject
*
)
it_i
->
second
).
inc_ref
();
}
}
...
@@ -262,7 +305,8 @@ template <typename type> class type_caster_base : public type_caster_generic {
...
@@ -262,7 +305,8 @@ template <typename type> class type_caster_base : public type_caster_generic {
public:
public:
static
PYBIND11_DESCR
name
()
{
return
type_descr
(
_
<
type
>
());
}
static
PYBIND11_DESCR
name
()
{
return
type_descr
(
_
<
type
>
());
}
type_caster_base
()
:
type_caster_generic
(
typeid
(
type
))
{
}
type_caster_base
()
:
type_caster_base
(
typeid
(
type
))
{
}
type_caster_base
(
const
std
::
type_info
&
info
)
:
type_caster_generic
(
info
)
{
}
static
handle
cast
(
const
itype
&
src
,
return_value_policy
policy
,
handle
parent
)
{
static
handle
cast
(
const
itype
&
src
,
return_value_policy
policy
,
handle
parent
)
{
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
...
@@ -299,10 +343,10 @@ protected:
...
@@ -299,10 +343,10 @@ protected:
#else
#else
/* Visual Studio 2015's SFINAE implementation doesn't yet handle the above robustly in all situations.
/* Visual Studio 2015's SFINAE implementation doesn't yet handle the above robustly in all situations.
Use a workaround that only tests for constructibility for now. */
Use a workaround that only tests for constructibility for now. */
template
<
typename
T
=
type
,
typename
=
typename
std
::
enable_if
<
std
::
is_copy_constructible
<
T
>
::
value
>
::
type
>
template
<
typename
T
=
type
,
typename
=
enable_if
_t
<
std
::
is_copy_constructible
<
T
>
::
value
>>
static
Constructor
make_copy_constructor
(
const
T
*
value
)
{
static
Constructor
make_copy_constructor
(
const
T
*
value
)
{
return
[](
const
void
*
arg
)
->
void
*
{
return
new
T
(
*
((
const
T
*
)
arg
));
};
}
return
[](
const
void
*
arg
)
->
void
*
{
return
new
T
(
*
((
const
T
*
)
arg
));
};
}
template
<
typename
T
=
type
,
typename
=
typename
std
::
enable_if
<
std
::
is_move_constructible
<
T
>
::
value
>
::
type
>
template
<
typename
T
=
type
,
typename
=
enable_if
_t
<
std
::
is_move_constructible
<
T
>
::
value
>>
static
Constructor
make_move_constructor
(
const
T
*
value
)
{
static
Constructor
make_move_constructor
(
const
T
*
value
)
{
return
[](
const
void
*
arg
)
->
void
*
{
return
(
void
*
)
new
T
(
std
::
move
(
*
((
T
*
)
arg
)));
};
}
return
[](
const
void
*
arg
)
->
void
*
{
return
(
void
*
)
new
T
(
std
::
move
(
*
((
T
*
)
arg
)));
};
}
#endif
#endif
...
@@ -343,8 +387,8 @@ public:
...
@@ -343,8 +387,8 @@ public:
template
<
typename
T
>
template
<
typename
T
>
struct
type_caster
<
struct
type_caster
<
T
,
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
||
T
,
enable_if
_t
<
std
::
is_integral
<
T
>::
value
||
std
::
is_floating_point
<
T
>::
value
>
::
type
>
{
std
::
is_floating_point
<
T
>::
value
>>
{
typedef
typename
std
::
conditional
<
sizeof
(
T
)
<=
sizeof
(
long
),
long
,
long
long
>::
type
_py_type_0
;
typedef
typename
std
::
conditional
<
sizeof
(
T
)
<=
sizeof
(
long
),
long
,
long
long
>::
type
_py_type_0
;
typedef
typename
std
::
conditional
<
std
::
is_signed
<
T
>::
value
,
_py_type_0
,
typename
std
::
make_unsigned
<
_py_type_0
>::
type
>::
type
_py_type_1
;
typedef
typename
std
::
conditional
<
std
::
is_signed
<
T
>::
value
,
_py_type_0
,
typename
std
::
make_unsigned
<
_py_type_0
>::
type
>::
type
_py_type_1
;
typedef
typename
std
::
conditional
<
std
::
is_floating_point
<
T
>::
value
,
double
,
_py_type_1
>::
type
py_type
;
typedef
typename
std
::
conditional
<
std
::
is_floating_point
<
T
>::
value
,
double
,
_py_type_1
>::
type
py_type
;
...
@@ -433,7 +477,7 @@ public:
...
@@ -433,7 +477,7 @@ public:
}
}
/* Check if this is a C++ type */
/* Check if this is a C++ type */
if
(
get_type_info
((
PyTypeObject
*
)
h
.
get_type
().
ptr
()
,
false
))
{
if
(
get_type_info
((
PyTypeObject
*
)
h
.
get_type
().
ptr
()))
{
value
=
((
instance
<
void
>
*
)
h
.
ptr
())
->
value
;
value
=
((
instance
<
void
>
*
)
h
.
ptr
())
->
value
;
return
true
;
return
true
;
}
}
...
@@ -658,20 +702,20 @@ public:
...
@@ -658,20 +702,20 @@ public:
return
load
(
src
,
convert
,
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
return
load
(
src
,
convert
,
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
}
}
template
<
typename
T
=
itype
,
typename
std
::
enable_if
<
template
<
typename
T
=
itype
,
enable_if
_t
<
!
std
::
is_same
<
T
,
args_type
>
::
value
&&
!
std
::
is_same
<
T
,
args_type
>
::
value
&&
!
std
::
is_same
<
T
,
args_kwargs_type
>::
value
,
int
>
::
type
=
0
>
!
std
::
is_same
<
T
,
args_kwargs_type
>::
value
,
int
>
=
0
>
bool
load_args
(
handle
args
,
handle
,
bool
convert
)
{
bool
load_args
(
handle
args
,
handle
,
bool
convert
)
{
return
load
(
args
,
convert
,
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
return
load
(
args
,
convert
,
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
}
}
template
<
typename
T
=
itype
,
typename
std
::
enable_if
<
std
::
is_same
<
T
,
args_type
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
T
=
itype
,
enable_if
_t
<
std
::
is_same
<
T
,
args_type
>
::
value
,
int
>
=
0
>
bool
load_args
(
handle
args
,
handle
,
bool
convert
)
{
bool
load_args
(
handle
args
,
handle
,
bool
convert
)
{
std
::
get
<
0
>
(
value
).
load
(
args
,
convert
);
std
::
get
<
0
>
(
value
).
load
(
args
,
convert
);
return
true
;
return
true
;
}
}
template
<
typename
T
=
itype
,
typename
std
::
enable_if
<
std
::
is_same
<
T
,
args_kwargs_type
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
T
=
itype
,
enable_if
_t
<
std
::
is_same
<
T
,
args_kwargs_type
>
::
value
,
int
>
=
0
>
bool
load_args
(
handle
args
,
handle
kwargs
,
bool
convert
)
{
bool
load_args
(
handle
args
,
handle
kwargs
,
bool
convert
)
{
std
::
get
<
0
>
(
value
).
load
(
args
,
convert
);
std
::
get
<
0
>
(
value
).
load
(
args
,
convert
);
std
::
get
<
1
>
(
value
).
load
(
kwargs
,
convert
);
std
::
get
<
1
>
(
value
).
load
(
kwargs
,
convert
);
...
@@ -690,11 +734,11 @@ public:
...
@@ -690,11 +734,11 @@ public:
return
type_descr
(
_
(
"Tuple["
)
+
element_names
()
+
_
(
"]"
));
return
type_descr
(
_
(
"Tuple["
)
+
element_names
()
+
_
(
"]"
));
}
}
template
<
typename
ReturnValue
,
typename
Func
>
typename
std
::
enable_if
<!
std
::
is_void
<
ReturnValue
>::
value
,
ReturnValue
>
::
type
call
(
Func
&&
f
)
{
template
<
typename
ReturnValue
,
typename
Func
>
enable_if
_t
<!
std
::
is_void
<
ReturnValue
>::
value
,
ReturnValue
>
call
(
Func
&&
f
)
{
return
call
<
ReturnValue
>
(
std
::
forward
<
Func
>
(
f
),
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
return
call
<
ReturnValue
>
(
std
::
forward
<
Func
>
(
f
),
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
}
}
template
<
typename
ReturnValue
,
typename
Func
>
typename
std
::
enable_if
<
std
::
is_void
<
ReturnValue
>::
value
,
void_type
>
::
type
call
(
Func
&&
f
)
{
template
<
typename
ReturnValue
,
typename
Func
>
enable_if
_t
<
std
::
is_void
<
ReturnValue
>::
value
,
void_type
>
call
(
Func
&&
f
)
{
call
<
ReturnValue
>
(
std
::
forward
<
Func
>
(
f
),
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
call
<
ReturnValue
>
(
std
::
forward
<
Func
>
(
f
),
typename
make_index_sequence
<
sizeof
...(
Tuple
)
>::
type
());
return
void_type
();
return
void_type
();
}
}
...
@@ -749,22 +793,56 @@ protected:
...
@@ -749,22 +793,56 @@ protected:
/// Type caster for holder types like std::shared_ptr, etc.
/// Type caster for holder types like std::shared_ptr, etc.
template
<
typename
type
,
typename
holder_type
>
class
type_caster_holder
:
public
type_caster_base
<
type
>
{
template
<
typename
type
,
typename
holder_type
>
class
type_caster_holder
:
public
type_caster_base
<
type
>
{
public:
public:
using
type_caster_base
<
type
>::
cast
;
using
base
=
type_caster_base
<
type
>
;
using
type_caster_base
<
type
>::
typeinfo
;
using
base
::
base
;
using
type_caster_base
<
type
>::
value
;
using
base
::
cast
;
using
type_caster_base
<
type
>::
temp
;
using
base
::
typeinfo
;
using
base
::
value
;
using
base
::
temp
;
bool
load
(
handle
src
,
bool
convert
)
{
PYBIND11_NOINLINE
bool
load
(
handle
src
,
bool
convert
)
{
if
(
!
src
||
!
typeinfo
)
{
return
load
(
src
,
convert
,
Py_TYPE
(
src
.
ptr
()));
}
bool
load
(
handle
src
,
bool
convert
,
PyTypeObject
*
tobj
)
{
if
(
!
src
||
!
typeinfo
)
return
false
;
return
false
;
}
else
if
(
src
.
is_none
())
{
if
(
src
.
is_none
())
{
value
=
nullptr
;
value
=
nullptr
;
return
true
;
return
true
;
}
else
if
(
PyType_IsSubtype
(
Py_TYPE
(
src
.
ptr
()),
typeinfo
->
type
))
{
}
auto
inst
=
(
instance
<
type
,
holder_type
>
*
)
src
.
ptr
();
value
=
(
void
*
)
inst
->
value
;
if
(
typeinfo
->
simple_type
)
{
/* Case 1: no multiple inheritance etc. involved */
holder
=
inst
->
holder
;
/* Check if we can safely perform a reinterpret-style cast */
return
true
;
if
(
PyType_IsSubtype
(
tobj
,
typeinfo
->
type
))
{
auto
inst
=
(
instance
<
type
,
holder_type
>
*
)
src
.
ptr
();
value
=
(
void
*
)
inst
->
value
;
holder
=
inst
->
holder
;
return
true
;
}
}
else
{
/* Case 2: multiple inheritance */
/* Check if we can safely perform a reinterpret-style cast */
if
(
tobj
==
typeinfo
->
type
)
{
auto
inst
=
(
instance
<
type
,
holder_type
>
*
)
src
.
ptr
();
value
=
(
void
*
)
inst
->
value
;
holder
=
inst
->
holder
;
return
true
;
}
/* If this is a python class, also check the parents recursively */
auto
const
&
type_dict
=
get_internals
().
registered_types_py
;
bool
new_style_class
=
PyType_Check
(
tobj
);
if
(
type_dict
.
find
(
tobj
)
==
type_dict
.
end
()
&&
new_style_class
&&
tobj
->
tp_bases
)
{
tuple
parents
(
tobj
->
tp_bases
,
true
);
for
(
handle
parent
:
parents
)
{
bool
result
=
load
(
src
,
convert
,
(
PyTypeObject
*
)
parent
.
ptr
());
if
(
result
)
return
true
;
}
}
if
(
try_implicit_casts
(
src
,
convert
))
return
true
;
}
}
if
(
convert
)
{
if
(
convert
)
{
...
@@ -774,6 +852,23 @@ public:
...
@@ -774,6 +852,23 @@ public:
return
true
;
return
true
;
}
}
}
}
return
false
;
}
template
<
typename
T
=
holder_type
,
detail
::
enable_if_t
<!
std
::
is_constructible
<
T
,
const
T
&
,
type
*
>
::
value
,
int
>
=
0
>
bool
try_implicit_casts
(
handle
,
bool
)
{
return
false
;
}
template
<
typename
T
=
holder_type
,
detail
::
enable_if_t
<
std
::
is_constructible
<
T
,
const
T
&
,
type
*
>
::
value
,
int
>
=
0
>
bool
try_implicit_casts
(
handle
src
,
bool
convert
)
{
for
(
auto
&
cast
:
typeinfo
->
implicit_casts
)
{
type_caster_holder
sub_caster
(
*
cast
.
first
);
if
(
sub_caster
.
load
(
src
,
convert
))
{
value
=
cast
.
second
(
sub_caster
.
value
);
holder
=
holder_type
(
sub_caster
.
holder
,
(
type
*
)
value
);
return
true
;
}
}
return
false
;
return
false
;
}
}
...
@@ -813,12 +908,12 @@ template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { retur
...
@@ -813,12 +908,12 @@ template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { retur
template
<
>
struct
handle_type_name
<
kwargs
>
{
static
PYBIND11_DESCR
name
()
{
return
_
(
"**kwargs"
);
}
};
template
<
>
struct
handle_type_name
<
kwargs
>
{
static
PYBIND11_DESCR
name
()
{
return
_
(
"**kwargs"
);
}
};
template
<
typename
type
>
template
<
typename
type
>
struct
type_caster
<
type
,
typename
std
::
enable_if
<
std
::
is_base_of
<
handle
,
type
>::
value
>
::
type
>
{
struct
type_caster
<
type
,
enable_if
_t
<
std
::
is_base_of
<
handle
,
type
>::
value
>>
{
public:
public:
template
<
typename
T
=
type
,
typename
std
::
enable_if
<!
std
::
is_base_of
<
object
,
T
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
T
=
type
,
enable_if
_t
<!
std
::
is_base_of
<
object
,
T
>
::
value
,
int
>
=
0
>
bool
load
(
handle
src
,
bool
/* convert */
)
{
value
=
type
(
src
);
return
value
.
check
();
}
bool
load
(
handle
src
,
bool
/* convert */
)
{
value
=
type
(
src
);
return
value
.
check
();
}
template
<
typename
T
=
type
,
typename
std
::
enable_if
<
std
::
is_base_of
<
object
,
T
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
T
=
type
,
enable_if
_t
<
std
::
is_base_of
<
object
,
T
>
::
value
,
int
>
=
0
>
bool
load
(
handle
src
,
bool
/* convert */
)
{
value
=
type
(
src
,
true
);
return
value
.
check
();
}
bool
load
(
handle
src
,
bool
/* convert */
)
{
value
=
type
(
src
,
true
);
return
value
.
check
();
}
static
handle
cast
(
const
handle
&
src
,
return_value_policy
/* policy */
,
handle
/* parent */
)
{
static
handle
cast
(
const
handle
&
src
,
return_value_policy
/* policy */
,
handle
/* parent */
)
{
...
@@ -837,21 +932,21 @@ public:
...
@@ -837,21 +932,21 @@ public:
// must have ref_count() == 1)h
// must have ref_count() == 1)h
// If any of the above are not satisfied, we fall back to copying.
// If any of the above are not satisfied, we fall back to copying.
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
move_is_plain_type
:
std
::
false_type
{};
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
move_is_plain_type
:
std
::
false_type
{};
template
<
typename
T
>
struct
move_is_plain_type
<
T
,
typename
std
::
enable_if
<
template
<
typename
T
>
struct
move_is_plain_type
<
T
,
enable_if
_t
<
!
std
::
is_void
<
T
>::
value
&&
!
std
::
is_pointer
<
T
>::
value
&&
!
std
::
is_reference
<
T
>::
value
&&
!
std
::
is_const
<
T
>::
value
!
std
::
is_void
<
T
>::
value
&&
!
std
::
is_pointer
<
T
>::
value
&&
!
std
::
is_reference
<
T
>::
value
&&
!
std
::
is_const
<
T
>::
value
>
::
type
>
:
std
::
true_type
{};
>>
:
std
::
true_type
{
};
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
move_always
:
std
::
false_type
{};
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
move_always
:
std
::
false_type
{};
template
<
typename
T
>
struct
move_always
<
T
,
typename
std
::
enable_if
<
template
<
typename
T
>
struct
move_always
<
T
,
enable_if
_t
<
move_is_plain_type
<
T
>::
value
&&
move_is_plain_type
<
T
>::
value
&&
!
std
::
is_copy_constructible
<
T
>::
value
&&
std
::
is_move_constructible
<
T
>::
value
&&
!
std
::
is_copy_constructible
<
T
>::
value
&&
std
::
is_move_constructible
<
T
>::
value
&&
std
::
is_same
<
decltype
(
std
::
declval
<
type_caster
<
T
>>
().
operator
T
&
()),
T
&>::
value
std
::
is_same
<
decltype
(
std
::
declval
<
type_caster
<
T
>>
().
operator
T
&
()),
T
&>::
value
>
::
type
>
:
std
::
true_type
{};
>>
:
std
::
true_type
{
};
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
move_if_unreferenced
:
std
::
false_type
{};
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
move_if_unreferenced
:
std
::
false_type
{};
template
<
typename
T
>
struct
move_if_unreferenced
<
T
,
typename
std
::
enable_if
<
template
<
typename
T
>
struct
move_if_unreferenced
<
T
,
enable_if
_t
<
move_is_plain_type
<
T
>::
value
&&
move_is_plain_type
<
T
>::
value
&&
!
move_always
<
T
>::
value
&&
std
::
is_move_constructible
<
T
>::
value
&&
!
move_always
<
T
>::
value
&&
std
::
is_move_constructible
<
T
>::
value
&&
std
::
is_same
<
decltype
(
std
::
declval
<
type_caster
<
T
>>
().
operator
T
&
()),
T
&>::
value
std
::
is_same
<
decltype
(
std
::
declval
<
type_caster
<
T
>>
().
operator
T
&
()),
T
&>::
value
>
::
type
>
:
std
::
true_type
{};
>>
:
std
::
true_type
{
};
template
<
typename
T
>
using
move_never
=
std
::
integral_constant
<
bool
,
!
move_always
<
T
>::
value
&&
!
move_if_unreferenced
<
T
>::
value
>
;
template
<
typename
T
>
using
move_never
=
std
::
integral_constant
<
bool
,
!
move_always
<
T
>::
value
&&
!
move_if_unreferenced
<
T
>::
value
>
;
// Detect whether returning a `type` from a cast on type's type_caster is going to result in a
// Detect whether returning a `type` from a cast on type's type_caster is going to result in a
...
@@ -968,7 +1063,6 @@ template <> inline void cast_safe<void>(object &&) {}
...
@@ -968,7 +1063,6 @@ template <> inline void cast_safe<void>(object &&) {}
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
tuple
make_tuple
(
Args
&&
...
args_
)
{
typename
...
Args
>
tuple
make_tuple
(
Args
&&
...
args_
)
{
const
size_t
size
=
sizeof
...(
Args
);
const
size_t
size
=
sizeof
...(
Args
);
...
@@ -1023,7 +1117,7 @@ struct arg_v : arg {
...
@@ -1023,7 +1117,7 @@ struct arg_v : arg {
template
<
typename
T
>
template
<
typename
T
>
arg_v
arg
::
operator
=
(
T
&&
value
)
const
{
return
{
name
,
std
::
forward
<
T
>
(
value
)};
}
arg_v
arg
::
operator
=
(
T
&&
value
)
const
{
return
{
name
,
std
::
forward
<
T
>
(
value
)};
}
/// Alias for backward compatibility -- to be remove in version 2.0
/// Alias for backward compatibility -- to be remove
d
in version 2.0
template
<
typename
/*unused*/
>
using
arg_t
=
arg_v
;
template
<
typename
/*unused*/
>
using
arg_t
=
arg_v
;
inline
namespace
literals
{
inline
namespace
literals
{
...
@@ -1199,7 +1293,7 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
...
@@ -1199,7 +1293,7 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
"Invalid function call: positional args must precede keywords and ** unpacking; "
"Invalid function call: positional args must precede keywords and ** unpacking; "
"* unpacking must precede ** unpacking"
"* unpacking must precede ** unpacking"
);
);
return
{
std
::
forward
<
Args
>
(
args
)...};
return
{
std
::
forward
<
Args
>
(
args
)...
};
}
}
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
...
...
include/pybind11/common.h
View file @
d922dffe
...
@@ -30,6 +30,16 @@
...
@@ -30,6 +30,16 @@
# define PYBIND11_NOINLINE __attribute__ ((noinline))
# define PYBIND11_NOINLINE __attribute__ ((noinline))
#endif
#endif
#if __cplusplus > 201103L
# define PYBIND11_DEPRECATED(reason) [[deprecated(reason)]]
#elif defined(__clang__)
# define PYBIND11_DEPRECATED(reason) __attribute__((deprecated(reason)))
#elif defined(__GNUG__)
# define PYBIND11_DEPRECATED(reason) __attribute__((deprecated))
#elif defined(_MSC_VER)
# define PYBIND11_DEPRECATED(reason) __declspec(deprecated)
#endif
#define PYBIND11_VERSION_MAJOR 1
#define PYBIND11_VERSION_MAJOR 1
#define PYBIND11_VERSION_MINOR 9
#define PYBIND11_VERSION_MINOR 9
#define PYBIND11_VERSION_PATCH dev0
#define PYBIND11_VERSION_PATCH dev0
...
@@ -79,6 +89,7 @@
...
@@ -79,6 +89,7 @@
#include <unordered_map>
#include <unordered_map>
#include <memory>
#include <memory>
#include <typeindex>
#include <typeindex>
#include <type_traits>
#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions
#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions
#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
...
@@ -431,14 +442,14 @@ PYBIND11_RUNTIME_EXCEPTION(reference_cast_error, PyExc_RuntimeError) /// Used in
...
@@ -431,14 +442,14 @@ PYBIND11_RUNTIME_EXCEPTION(reference_cast_error, PyExc_RuntimeError) /// Used in
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
format_descriptor
{
};
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
format_descriptor
{
};
template
<
typename
T
>
struct
format_descriptor
<
T
,
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>
::
type
>
{
template
<
typename
T
>
struct
format_descriptor
<
T
,
detail
::
enable_if
_t
<
std
::
is_integral
<
T
>::
value
>>
{
static
constexpr
const
char
value
[
2
]
=
static
constexpr
const
char
value
[
2
]
=
{
"bBhHiIqQ"
[
detail
::
log2
(
sizeof
(
T
))
*
2
+
(
std
::
is_unsigned
<
T
>::
value
?
1
:
0
)],
'\0'
};
{
"bBhHiIqQ"
[
detail
::
log2
(
sizeof
(
T
))
*
2
+
(
std
::
is_unsigned
<
T
>::
value
?
1
:
0
)],
'\0'
};
static
std
::
string
format
()
{
return
value
;
}
static
std
::
string
format
()
{
return
value
;
}
};
};
template
<
typename
T
>
constexpr
const
char
format_descriptor
<
template
<
typename
T
>
constexpr
const
char
format_descriptor
<
T
,
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>
::
type
>::
value
[
2
];
T
,
detail
::
enable_if
_t
<
std
::
is_integral
<
T
>::
value
>>::
value
[
2
];
/// RAII wrapper that temporarily clears any Python error state
/// RAII wrapper that temporarily clears any Python error state
struct
error_scope
{
struct
error_scope
{
...
...
include/pybind11/descr.h
View file @
d922dffe
...
@@ -86,11 +86,11 @@ template <size_t...Digits> struct int_to_str<0, Digits...> {
...
@@ -86,11 +86,11 @@ template <size_t...Digits> struct int_to_str<0, Digits...> {
// Ternary description (like std::conditional)
// Ternary description (like std::conditional)
template
<
bool
B
,
size_t
Size1
,
size_t
Size2
>
template
<
bool
B
,
size_t
Size1
,
size_t
Size2
>
constexpr
typename
std
::
enable_if
<
B
,
descr
<
Size1
-
1
,
0
>>
::
type
_
(
char
const
(
&
text1
)[
Size1
],
char
const
(
&
)[
Size2
])
{
constexpr
enable_if
_t
<
B
,
descr
<
Size1
-
1
,
0
>>
_
(
char
const
(
&
text1
)[
Size1
],
char
const
(
&
)[
Size2
])
{
return
_
(
text1
);
return
_
(
text1
);
}
}
template
<
bool
B
,
size_t
Size1
,
size_t
Size2
>
template
<
bool
B
,
size_t
Size1
,
size_t
Size2
>
constexpr
typename
std
::
enable_if
<!
B
,
descr
<
Size2
-
1
,
0
>>
::
type
_
(
char
const
(
&
)[
Size1
],
char
const
(
&
text2
)[
Size2
])
{
constexpr
enable_if
_t
<!
B
,
descr
<
Size2
-
1
,
0
>>
_
(
char
const
(
&
)[
Size1
],
char
const
(
&
text2
)[
Size2
])
{
return
_
(
text2
);
return
_
(
text2
);
}
}
...
@@ -164,8 +164,8 @@ PYBIND11_NOINLINE inline descr _(const char *text) {
...
@@ -164,8 +164,8 @@ PYBIND11_NOINLINE inline descr _(const char *text) {
return
descr
(
text
,
types
);
return
descr
(
text
,
types
);
}
}
template
<
bool
B
>
PYBIND11_NOINLINE
typename
std
::
enable_if
<
B
,
descr
>
::
type
_
(
const
char
*
text1
,
const
char
*
)
{
return
_
(
text1
);
}
template
<
bool
B
>
PYBIND11_NOINLINE
enable_if
_t
<
B
,
descr
>
_
(
const
char
*
text1
,
const
char
*
)
{
return
_
(
text1
);
}
template
<
bool
B
>
PYBIND11_NOINLINE
typename
std
::
enable_if
<!
B
,
descr
>
::
type
_
(
char
const
*
,
const
char
*
text2
)
{
return
_
(
text2
);
}
template
<
bool
B
>
PYBIND11_NOINLINE
enable_if
_t
<!
B
,
descr
>
_
(
char
const
*
,
const
char
*
text2
)
{
return
_
(
text2
);
}
template
<
typename
Type
>
PYBIND11_NOINLINE
descr
_
()
{
template
<
typename
Type
>
PYBIND11_NOINLINE
descr
_
()
{
const
std
::
type_info
*
types
[
2
]
=
{
&
typeid
(
Type
),
nullptr
};
const
std
::
type_info
*
types
[
2
]
=
{
&
typeid
(
Type
),
nullptr
};
...
...
include/pybind11/eigen.h
View file @
d922dffe
...
@@ -46,9 +46,9 @@ public:
...
@@ -46,9 +46,9 @@ public:
// type_caster to handle argument copying/forwarding.
// type_caster to handle argument copying/forwarding.
template
<
typename
T
>
class
is_eigen_ref
{
template
<
typename
T
>
class
is_eigen_ref
{
private:
private:
template
<
typename
Derived
>
static
typename
std
::
enable_if
<
template
<
typename
Derived
>
static
enable_if
_t
<
std
::
is_same
<
typename
std
::
remove_const
<
T
>::
type
,
Eigen
::
Ref
<
Derived
>>::
value
,
std
::
is_same
<
typename
std
::
remove_const
<
T
>::
type
,
Eigen
::
Ref
<
Derived
>>::
value
,
Derived
>
::
type
test
(
const
Eigen
::
Ref
<
Derived
>
&
);
Derived
>
test
(
const
Eigen
::
Ref
<
Derived
>
&
);
static
void
test
(...);
static
void
test
(...);
public:
public:
typedef
decltype
(
test
(
std
::
declval
<
T
>
()))
Derived
;
typedef
decltype
(
test
(
std
::
declval
<
T
>
()))
Derived
;
...
@@ -77,7 +77,7 @@ public:
...
@@ -77,7 +77,7 @@ public:
};
};
template
<
typename
Type
>
template
<
typename
Type
>
struct
type_caster
<
Type
,
typename
std
::
enable_if
<
is_eigen_dense
<
Type
>::
value
&&
!
is_eigen_ref
<
Type
>::
value
>
::
type
>
{
struct
type_caster
<
Type
,
enable_if
_t
<
is_eigen_dense
<
Type
>::
value
&&
!
is_eigen_ref
<
Type
>::
value
>>
{
typedef
typename
Type
::
Scalar
Scalar
;
typedef
typename
Type
::
Scalar
Scalar
;
static
constexpr
bool
rowMajor
=
Type
::
Flags
&
Eigen
::
RowMajorBit
;
static
constexpr
bool
rowMajor
=
Type
::
Flags
&
Eigen
::
RowMajorBit
;
static
constexpr
bool
isVector
=
Type
::
IsVectorAtCompileTime
;
static
constexpr
bool
isVector
=
Type
::
IsVectorAtCompileTime
;
...
@@ -149,18 +149,18 @@ struct type_caster<Type, typename std::enable_if<is_eigen_dense<Type>::value &&
...
@@ -149,18 +149,18 @@ struct type_caster<Type, typename std::enable_if<is_eigen_dense<Type>::value &&
_
(
"["
)
+
rows
()
+
_
(
", "
)
+
cols
()
+
_
(
"]]"
));
_
(
"["
)
+
rows
()
+
_
(
", "
)
+
cols
()
+
_
(
"]]"
));
protected:
protected:
template
<
typename
T
=
Type
,
typename
std
::
enable_if
<
T
::
RowsAtCompileTime
==
Eigen
::
Dynamic
,
int
>
::
type
=
0
>
template
<
typename
T
=
Type
,
enable_if
_t
<
T
::
RowsAtCompileTime
==
Eigen
::
Dynamic
,
int
>
=
0
>
static
PYBIND11_DESCR
rows
()
{
return
_
(
"m"
);
}
static
PYBIND11_DESCR
rows
()
{
return
_
(
"m"
);
}
template
<
typename
T
=
Type
,
typename
std
::
enable_if
<
T
::
RowsAtCompileTime
!=
Eigen
::
Dynamic
,
int
>
::
type
=
0
>
template
<
typename
T
=
Type
,
enable_if
_t
<
T
::
RowsAtCompileTime
!=
Eigen
::
Dynamic
,
int
>
=
0
>
static
PYBIND11_DESCR
rows
()
{
return
_
<
T
::
RowsAtCompileTime
>
();
}
static
PYBIND11_DESCR
rows
()
{
return
_
<
T
::
RowsAtCompileTime
>
();
}
template
<
typename
T
=
Type
,
typename
std
::
enable_if
<
T
::
ColsAtCompileTime
==
Eigen
::
Dynamic
,
int
>
::
type
=
0
>
template
<
typename
T
=
Type
,
enable_if
_t
<
T
::
ColsAtCompileTime
==
Eigen
::
Dynamic
,
int
>
=
0
>
static
PYBIND11_DESCR
cols
()
{
return
_
(
"n"
);
}
static
PYBIND11_DESCR
cols
()
{
return
_
(
"n"
);
}
template
<
typename
T
=
Type
,
typename
std
::
enable_if
<
T
::
ColsAtCompileTime
!=
Eigen
::
Dynamic
,
int
>
::
type
=
0
>
template
<
typename
T
=
Type
,
enable_if
_t
<
T
::
ColsAtCompileTime
!=
Eigen
::
Dynamic
,
int
>
=
0
>
static
PYBIND11_DESCR
cols
()
{
return
_
<
T
::
ColsAtCompileTime
>
();
}
static
PYBIND11_DESCR
cols
()
{
return
_
<
T
::
ColsAtCompileTime
>
();
}
};
};
template
<
typename
Type
>
template
<
typename
Type
>
struct
type_caster
<
Type
,
typename
std
::
enable_if
<
is_eigen_dense
<
Type
>::
value
&&
is_eigen_ref
<
Type
>::
value
>
::
type
>
{
struct
type_caster
<
Type
,
enable_if
_t
<
is_eigen_dense
<
Type
>::
value
&&
is_eigen_ref
<
Type
>::
value
>>
{
protected:
protected:
using
Derived
=
typename
std
::
remove_const
<
typename
is_eigen_ref
<
Type
>::
Derived
>::
type
;
using
Derived
=
typename
std
::
remove_const
<
typename
is_eigen_ref
<
Type
>::
Derived
>::
type
;
using
DerivedCaster
=
type_caster
<
Derived
>
;
using
DerivedCaster
=
type_caster
<
Derived
>
;
...
@@ -181,7 +181,7 @@ public:
...
@@ -181,7 +181,7 @@ public:
// type_caster for special matrix types (e.g. DiagonalMatrix): load() is not supported, but we can
// type_caster for special matrix types (e.g. DiagonalMatrix): load() is not supported, but we can
// cast them into the python domain by first copying to a regular Eigen::Matrix, then casting that.
// cast them into the python domain by first copying to a regular Eigen::Matrix, then casting that.
template
<
typename
Type
>
template
<
typename
Type
>
struct
type_caster
<
Type
,
typename
std
::
enable_if
<
is_eigen_base
<
Type
>::
value
&&
!
is_eigen_ref
<
Type
>::
value
>
::
type
>
{
struct
type_caster
<
Type
,
enable_if
_t
<
is_eigen_base
<
Type
>::
value
&&
!
is_eigen_ref
<
Type
>::
value
>>
{
protected:
protected:
using
Matrix
=
Eigen
::
Matrix
<
typename
Type
::
Scalar
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
;
using
Matrix
=
Eigen
::
Matrix
<
typename
Type
::
Scalar
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
;
using
MatrixCaster
=
type_caster
<
Matrix
>
;
using
MatrixCaster
=
type_caster
<
Matrix
>
;
...
@@ -198,7 +198,7 @@ public:
...
@@ -198,7 +198,7 @@ public:
};
};
template
<
typename
Type
>
template
<
typename
Type
>
struct
type_caster
<
Type
,
typename
std
::
enable_if
<
is_eigen_sparse
<
Type
>::
value
>
::
type
>
{
struct
type_caster
<
Type
,
enable_if
_t
<
is_eigen_sparse
<
Type
>::
value
>>
{
typedef
typename
Type
::
Scalar
Scalar
;
typedef
typename
Type
::
Scalar
Scalar
;
typedef
typename
std
::
remove_reference
<
decltype
(
*
std
::
declval
<
Type
>
().
outerIndexPtr
())
>::
type
StorageIndex
;
typedef
typename
std
::
remove_reference
<
decltype
(
*
std
::
declval
<
Type
>
().
outerIndexPtr
())
>::
type
StorageIndex
;
typedef
typename
Type
::
Index
Index
;
typedef
typename
Type
::
Index
Index
;
...
...
include/pybind11/numpy.h
View file @
d922dffe
...
@@ -486,7 +486,7 @@ public:
...
@@ -486,7 +486,7 @@ public:
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
format_descriptor
<
T
,
typename
std
::
enable_if
<
detail
::
is_pod_struct
<
T
>::
value
>
::
type
>
{
struct
format_descriptor
<
T
,
detail
::
enable_if
_t
<
detail
::
is_pod_struct
<
T
>::
value
>>
{
static
std
::
string
format
()
{
static
std
::
string
format
()
{
return
detail
::
npy_format_descriptor
<
typename
std
::
remove_cv
<
T
>::
type
>::
format
();
return
detail
::
npy_format_descriptor
<
typename
std
::
remove_cv
<
T
>::
type
>::
format
();
}
}
...
@@ -517,7 +517,7 @@ struct is_pod_struct {
...
@@ -517,7 +517,7 @@ struct is_pod_struct {
!
std
::
is_same
<
typename
std
::
remove_cv
<
T
>::
type
,
std
::
complex
<
double
>>::
value
};
!
std
::
is_same
<
typename
std
::
remove_cv
<
T
>::
type
,
std
::
complex
<
double
>>::
value
};
};
};
template
<
typename
T
>
struct
npy_format_descriptor
<
T
,
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>
::
type
>
{
template
<
typename
T
>
struct
npy_format_descriptor
<
T
,
enable_if
_t
<
std
::
is_integral
<
T
>::
value
>>
{
private:
private:
constexpr
static
const
int
values
[
8
]
=
{
constexpr
static
const
int
values
[
8
]
=
{
npy_api
::
NPY_BYTE_
,
npy_api
::
NPY_UBYTE_
,
npy_api
::
NPY_SHORT_
,
npy_api
::
NPY_USHORT_
,
npy_api
::
NPY_BYTE_
,
npy_api
::
NPY_UBYTE_
,
npy_api
::
NPY_SHORT_
,
npy_api
::
NPY_USHORT_
,
...
@@ -529,13 +529,13 @@ public:
...
@@ -529,13 +529,13 @@ public:
return
object
(
ptr
,
true
);
return
object
(
ptr
,
true
);
pybind11_fail
(
"Unsupported buffer format!"
);
pybind11_fail
(
"Unsupported buffer format!"
);
}
}
template
<
typename
T2
=
T
,
typename
std
::
enable_if
<
std
::
is_signed
<
T2
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
T2
=
T
,
enable_if
_t
<
std
::
is_signed
<
T2
>
::
value
,
int
>
=
0
>
static
PYBIND11_DESCR
name
()
{
return
_
(
"int"
)
+
_
<
sizeof
(
T
)
*
8
>
();
}
static
PYBIND11_DESCR
name
()
{
return
_
(
"int"
)
+
_
<
sizeof
(
T
)
*
8
>
();
}
template
<
typename
T2
=
T
,
typename
std
::
enable_if
<!
std
::
is_signed
<
T2
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
T2
=
T
,
enable_if
_t
<!
std
::
is_signed
<
T2
>
::
value
,
int
>
=
0
>
static
PYBIND11_DESCR
name
()
{
return
_
(
"uint"
)
+
_
<
sizeof
(
T
)
*
8
>
();
}
static
PYBIND11_DESCR
name
()
{
return
_
(
"uint"
)
+
_
<
sizeof
(
T
)
*
8
>
();
}
};
};
template
<
typename
T
>
constexpr
const
int
npy_format_descriptor
<
template
<
typename
T
>
constexpr
const
int
npy_format_descriptor
<
T
,
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
>
::
type
>::
values
[
8
];
T
,
enable_if
_t
<
std
::
is_integral
<
T
>::
value
>>::
values
[
8
];
#define DECL_FMT(Type, NumPyName, Name) template<> struct npy_format_descriptor<Type> { \
#define DECL_FMT(Type, NumPyName, Name) template<> struct npy_format_descriptor<Type> { \
enum { value = npy_api::NumPyName }; \
enum { value = npy_api::NumPyName }; \
...
@@ -568,7 +568,7 @@ struct field_descriptor {
...
@@ -568,7 +568,7 @@ struct field_descriptor {
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
npy_format_descriptor
<
T
,
typename
std
::
enable_if
<
is_pod_struct
<
T
>::
value
>
::
type
>
{
struct
npy_format_descriptor
<
T
,
enable_if
_t
<
is_pod_struct
<
T
>::
value
>>
{
static
PYBIND11_DESCR
name
()
{
return
_
(
"struct"
);
}
static
PYBIND11_DESCR
name
()
{
return
_
(
"struct"
);
}
static
pybind11
::
dtype
dtype
()
{
static
pybind11
::
dtype
dtype
()
{
...
@@ -634,9 +634,9 @@ private:
...
@@ -634,9 +634,9 @@ private:
};
};
template
<
typename
T
>
template
<
typename
T
>
std
::
string
npy_format_descriptor
<
T
,
typename
std
::
enable_if
<
is_pod_struct
<
T
>::
value
>
::
type
>::
format_str
;
std
::
string
npy_format_descriptor
<
T
,
enable_if
_t
<
is_pod_struct
<
T
>::
value
>>::
format_str
;
template
<
typename
T
>
template
<
typename
T
>
PyObject
*
npy_format_descriptor
<
T
,
typename
std
::
enable_if
<
is_pod_struct
<
T
>::
value
>
::
type
>::
dtype_ptr
=
nullptr
;
PyObject
*
npy_format_descriptor
<
T
,
enable_if
_t
<
is_pod_struct
<
T
>::
value
>>::
dtype_ptr
=
nullptr
;
// Extract name, offset and format descriptor for a struct field
// Extract name, offset and format descriptor for a struct field
#define PYBIND11_FIELD_DESCRIPTOR(Type, Field) \
#define PYBIND11_FIELD_DESCRIPTOR(Type, Field) \
...
...
include/pybind11/operators.h
View file @
d922dffe
...
@@ -10,7 +10,6 @@
...
@@ -10,7 +10,6 @@
#pragma once
#pragma once
#include "pybind11.h"
#include "pybind11.h"
#include <type_traits>
#if defined(__clang__) && !defined(__INTEL_COMPILER)
#if defined(__clang__) && !defined(__INTEL_COMPILER)
# pragma clang diagnostic ignored "-Wunsequenced" // multiple unsequenced modifications to 'self' (when using def(py::self OP Type()))
# pragma clang diagnostic ignored "-Wunsequenced" // multiple unsequenced modifications to 'self' (when using def(py::self OP Type()))
...
...
include/pybind11/pybind11.h
View file @
d922dffe
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
# pragma warning(disable: 4702) // warning C4702: unreachable code
#elif defined(__INTEL_COMPILER)
#elif defined(__INTEL_COMPILER)
# pragma warning(push)
# pragma warning(push)
# pragma warning(disable: 186) // pointless comparison of unsigned integer with zero
# pragma warning(disable: 186) // pointless comparison of unsigned integer with zero
...
@@ -460,8 +461,10 @@ protected:
...
@@ -460,8 +461,10 @@ protected:
if
(
overloads
->
is_operator
)
if
(
overloads
->
is_operator
)
return
handle
(
Py_NotImplemented
).
inc_ref
().
ptr
();
return
handle
(
Py_NotImplemented
).
inc_ref
().
ptr
();
std
::
string
msg
=
"Incompatible "
+
std
::
string
(
overloads
->
is_constructor
?
"constructor"
:
"function"
)
+
std
::
string
msg
=
std
::
string
(
overloads
->
name
)
+
"(): incompatible "
+
" arguments. The following argument types are supported:
\n
"
;
std
::
string
(
overloads
->
is_constructor
?
"constructor"
:
"function"
)
+
" arguments. The following argument types are supported:
\n
"
;
int
ctr
=
0
;
int
ctr
=
0
;
for
(
detail
::
function_record
*
it2
=
overloads
;
it2
!=
nullptr
;
it2
=
it2
->
next
)
{
for
(
detail
::
function_record
*
it2
=
overloads
;
it2
!=
nullptr
;
it2
=
it2
->
next
)
{
msg
+=
" "
+
std
::
to_string
(
++
ctr
)
+
". "
;
msg
+=
" "
+
std
::
to_string
(
++
ctr
)
+
". "
;
...
@@ -489,7 +492,7 @@ protected:
...
@@ -489,7 +492,7 @@ protected:
msg
+=
"
\n
"
;
msg
+=
"
\n
"
;
}
}
msg
+=
"
Invoked with: "
;
msg
+=
"
\n
Invoked with: "
;
tuple
args_
(
args
,
true
);
tuple
args_
(
args
,
true
);
for
(
size_t
ti
=
overloads
->
is_constructor
?
1
:
0
;
ti
<
args_
.
size
();
++
ti
)
{
for
(
size_t
ti
=
overloads
->
is_constructor
?
1
:
0
;
ti
<
args_
.
size
();
++
ti
)
{
msg
+=
static_cast
<
std
::
string
>
(
static_cast
<
object
>
(
args_
[
ti
]).
str
());
msg
+=
static_cast
<
std
::
string
>
(
static_cast
<
object
>
(
args_
[
ti
]).
str
());
...
@@ -574,18 +577,6 @@ public:
...
@@ -574,18 +577,6 @@ public:
PYBIND11_OBJECT_DEFAULT
(
generic_type
,
object
,
PyType_Check
)
PYBIND11_OBJECT_DEFAULT
(
generic_type
,
object
,
PyType_Check
)
protected:
protected:
void
initialize
(
type_record
*
rec
)
{
void
initialize
(
type_record
*
rec
)
{
if
(
rec
->
base_type
)
{
if
(
rec
->
base_handle
)
pybind11_fail
(
"generic_type: specified base type multiple times!"
);
rec
->
base_handle
=
detail
::
get_type_handle
(
*
(
rec
->
base_type
));
if
(
!
rec
->
base_handle
)
{
std
::
string
tname
(
rec
->
base_type
->
name
());
detail
::
clean_type_id
(
tname
);
pybind11_fail
(
"generic_type: type
\"
"
+
std
::
string
(
rec
->
name
)
+
"
\"
referenced unknown base type
\"
"
+
tname
+
"
\"
"
);
}
}
auto
&
internals
=
get_internals
();
auto
&
internals
=
get_internals
();
auto
tindex
=
std
::
type_index
(
*
(
rec
->
type
));
auto
tindex
=
std
::
type_index
(
*
(
rec
->
type
));
...
@@ -615,6 +606,12 @@ protected:
...
@@ -615,6 +606,12 @@ protected:
ht_qualname
=
name
;
ht_qualname
=
name
;
}
}
#endif
#endif
size_t
num_bases
=
rec
->
bases
.
size
();
tuple
bases
(
num_bases
);
for
(
size_t
i
=
0
;
i
<
num_bases
;
++
i
)
bases
[
i
]
=
rec
->
bases
[
i
];
std
::
string
full_name
=
(
scope_module
?
((
std
::
string
)
scope_module
.
str
()
+
"."
+
rec
->
name
)
std
::
string
full_name
=
(
scope_module
?
((
std
::
string
)
scope_module
.
str
()
+
"."
+
rec
->
name
)
:
std
::
string
(
rec
->
name
));
:
std
::
string
(
rec
->
name
));
...
@@ -627,11 +624,16 @@ protected:
...
@@ -627,11 +624,16 @@ protected:
memcpy
((
void
*
)
tp_doc
,
rec
->
doc
,
size
);
memcpy
((
void
*
)
tp_doc
,
rec
->
doc
,
size
);
}
}
/* Danger zone: from now (and until PyType_Ready), make sure to
issue no Python C API calls which could potentially invoke the
garbage collector (the GC will call type_traverse(), which will in
turn find the newly constructed type in an invalid state) */
object
type_holder
(
PyType_Type
.
tp_alloc
(
&
PyType_Type
,
0
),
false
);
object
type_holder
(
PyType_Type
.
tp_alloc
(
&
PyType_Type
,
0
),
false
);
auto
type
=
(
PyHeapTypeObject
*
)
type_holder
.
ptr
();
auto
type
=
(
PyHeapTypeObject
*
)
type_holder
.
ptr
();
if
(
!
type_holder
||
!
name
)
if
(
!
type_holder
||
!
name
)
pybind11_fail
(
"generic_type
:
u
nable to create type object!"
);
pybind11_fail
(
std
::
string
(
rec
->
name
)
+
"
:
U
nable to create type object!"
);
/* Register supplemental type information in C++ dict */
/* Register supplemental type information in C++ dict */
detail
::
type_info
*
tinfo
=
new
detail
::
type_info
();
detail
::
type_info
*
tinfo
=
new
detail
::
type_info
();
...
@@ -644,8 +646,12 @@ protected:
...
@@ -644,8 +646,12 @@ protected:
/* Basic type attributes */
/* Basic type attributes */
type
->
ht_type
.
tp_name
=
strdup
(
full_name
.
c_str
());
type
->
ht_type
.
tp_name
=
strdup
(
full_name
.
c_str
());
type
->
ht_type
.
tp_basicsize
=
(
ssize_t
)
rec
->
instance_size
;
type
->
ht_type
.
tp_basicsize
=
(
ssize_t
)
rec
->
instance_size
;
type
->
ht_type
.
tp_base
=
(
PyTypeObject
*
)
rec
->
base_handle
.
ptr
();
rec
->
base_handle
.
inc_ref
();
if
(
num_bases
>
0
)
{
type
->
ht_type
.
tp_base
=
(
PyTypeObject
*
)
((
object
)
bases
[
0
]).
inc_ref
().
ptr
();
type
->
ht_type
.
tp_bases
=
bases
.
release
().
ptr
();
rec
->
multiple_inheritance
|=
num_bases
>
1
;
}
type
->
ht_name
=
name
.
release
().
ptr
();
type
->
ht_name
=
name
.
release
().
ptr
();
...
@@ -676,7 +682,8 @@ protected:
...
@@ -676,7 +682,8 @@ protected:
type
->
ht_type
.
tp_doc
=
tp_doc
;
type
->
ht_type
.
tp_doc
=
tp_doc
;
if
(
PyType_Ready
(
&
type
->
ht_type
)
<
0
)
if
(
PyType_Ready
(
&
type
->
ht_type
)
<
0
)
pybind11_fail
(
"generic_type: PyType_Ready failed!"
);
pybind11_fail
(
std
::
string
(
rec
->
name
)
+
": PyType_Ready failed ("
+
detail
::
error_string
()
+
")!"
);
m_ptr
=
type_holder
.
ptr
();
m_ptr
=
type_holder
.
ptr
();
...
@@ -687,9 +694,23 @@ protected:
...
@@ -687,9 +694,23 @@ protected:
if
(
rec
->
scope
)
if
(
rec
->
scope
)
rec
->
scope
.
attr
(
handle
(
type
->
ht_name
))
=
*
this
;
rec
->
scope
.
attr
(
handle
(
type
->
ht_name
))
=
*
this
;
if
(
rec
->
multiple_inheritance
)
mark_parents_nonsimple
(
&
type
->
ht_type
);
type_holder
.
release
();
type_holder
.
release
();
}
}
/// Helper function which tags all parents of a type using mult. inheritance
void
mark_parents_nonsimple
(
PyTypeObject
*
value
)
{
tuple
t
(
value
->
tp_bases
,
true
);
for
(
handle
h
:
t
)
{
auto
tinfo2
=
get_type_info
((
PyTypeObject
*
)
h
.
ptr
());
if
(
tinfo2
)
tinfo2
->
simple_type
=
false
;
mark_parents_nonsimple
((
PyTypeObject
*
)
h
.
ptr
());
}
}
/// Allocate a metaclass on demand (for static properties)
/// Allocate a metaclass on demand (for static properties)
handle
metaclass
()
{
handle
metaclass
()
{
auto
&
ht_type
=
((
PyHeapTypeObject
*
)
m_ptr
)
->
ht_type
;
auto
&
ht_type
=
((
PyHeapTypeObject
*
)
m_ptr
)
->
ht_type
;
...
@@ -809,31 +830,18 @@ protected:
...
@@ -809,31 +830,18 @@ protected:
static
void
releasebuffer
(
PyObject
*
,
Py_buffer
*
view
)
{
delete
(
buffer_info
*
)
view
->
internal
;
}
static
void
releasebuffer
(
PyObject
*
,
Py_buffer
*
view
)
{
delete
(
buffer_info
*
)
view
->
internal
;
}
};
};
template
<
template
<
typename
>
class
Predicate
,
typename
...
BaseTypes
>
struct
class_selector
;
template
<
template
<
typename
>
class
Predicate
,
typename
Base
,
typename
...
Bases
>
struct
class_selector
<
Predicate
,
Base
,
Bases
...
>
{
static
inline
void
set_bases
(
detail
::
type_record
&
record
)
{
if
(
Predicate
<
Base
>::
value
)
record
.
base_type
=
&
typeid
(
Base
);
else
class_selector
<
Predicate
,
Bases
...
>::
set_bases
(
record
);
}
};
template
<
template
<
typename
>
class
Predicate
>
struct
class_selector
<
Predicate
>
{
static
inline
void
set_bases
(
detail
::
type_record
&
)
{}
};
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
template
<
typename
type_
,
typename
...
options
>
template
<
typename
type_
,
typename
...
options
>
class
class_
:
public
detail
::
generic_type
{
class
class_
:
public
detail
::
generic_type
{
template
<
typename
T
>
using
is_holder
=
detail
::
is_holder_type
<
type_
,
T
>
;
template
<
typename
T
>
using
is_holder
=
detail
::
is_holder_type
<
type_
,
T
>
;
template
<
typename
T
>
using
is_subtype
=
detail
::
bool_constant
<
std
::
is_base_of
<
type_
,
T
>::
value
&&
!
std
::
is_same
<
T
,
type_
>::
value
>
;
template
<
typename
T
>
using
is_subtype
=
detail
::
bool_constant
<
std
::
is_base_of
<
type_
,
T
>::
value
&&
!
std
::
is_same
<
T
,
type_
>::
value
>
;
template
<
typename
T
>
using
is_base
_class
=
detail
::
bool_constant
<
std
::
is_base_of
<
T
,
type_
>::
value
&&
!
std
::
is_same
<
T
,
type_
>::
value
>
;
template
<
typename
T
>
using
is_base
=
detail
::
bool_constant
<
std
::
is_base_of
<
T
,
type_
>::
value
&&
!
std
::
is_same
<
T
,
type_
>::
value
>
;
template
<
typename
T
>
using
is_valid_class_option
=
template
<
typename
T
>
using
is_valid_class_option
=
detail
::
bool_constant
<
detail
::
bool_constant
<
is_holder
<
T
>::
value
||
is_holder
<
T
>::
value
||
is_subtype
<
T
>::
value
||
is_subtype
<
T
>::
value
||
is_base
_class
<
T
>::
value
is_base
<
T
>::
value
>
;
>
;
public:
public:
...
@@ -846,9 +854,6 @@ public:
...
@@ -846,9 +854,6 @@ public:
static_assert
(
detail
::
all_of_t
<
is_valid_class_option
,
options
...
>::
value
,
static_assert
(
detail
::
all_of_t
<
is_valid_class_option
,
options
...
>::
value
,
"Unknown/invalid class_ template parameters provided"
);
"Unknown/invalid class_ template parameters provided"
);
static_assert
(
detail
::
count_t
<
is_base_class
,
options
...
>::
value
<=
1
,
"Invalid class_ base types: multiple inheritance is not supported"
);
PYBIND11_OBJECT
(
class_
,
detail
::
generic_type
,
PyType_Check
)
PYBIND11_OBJECT
(
class_
,
detail
::
generic_type
,
PyType_Check
)
template
<
typename
...
Extra
>
template
<
typename
...
Extra
>
...
@@ -862,7 +867,9 @@ public:
...
@@ -862,7 +867,9 @@ public:
record
.
init_holder
=
init_holder
;
record
.
init_holder
=
init_holder
;
record
.
dealloc
=
dealloc
;
record
.
dealloc
=
dealloc
;
detail
::
class_selector
<
is_base_class
,
options
...
>::
set_bases
(
record
);
/* Register base classes specified via template arguments to class_, if any */
bool
unused
[]
=
{
(
add_base
<
options
>
(
record
),
false
)...,
false
};
(
void
)
unused
;
/* Process optional arguments, if any */
/* Process optional arguments, if any */
detail
::
process_attributes
<
Extra
...
>::
init
(
extra
...,
&
record
);
detail
::
process_attributes
<
Extra
...
>::
init
(
extra
...,
&
record
);
...
@@ -875,6 +882,16 @@ public:
...
@@ -875,6 +882,16 @@ public:
}
}
}
}
template
<
typename
Base
,
detail
::
enable_if_t
<
is_base
<
Base
>
::
value
,
int
>
=
0
>
static
void
add_base
(
detail
::
type_record
&
rec
)
{
rec
.
add_base
(
&
typeid
(
Base
),
[](
void
*
src
)
->
void
*
{
return
static_cast
<
Base
*>
(
reinterpret_cast
<
type
*>
(
src
));
});
}
template
<
typename
Base
,
detail
::
enable_if_t
<!
is_base
<
Base
>
::
value
,
int
>
=
0
>
static
void
add_base
(
detail
::
type_record
&
)
{
}
template
<
typename
Func
,
typename
...
Extra
>
template
<
typename
Func
,
typename
...
Extra
>
class_
&
def
(
const
char
*
name_
,
Func
&&
f
,
const
Extra
&
...
extra
)
{
class_
&
def
(
const
char
*
name_
,
Func
&&
f
,
const
Extra
&
...
extra
)
{
cpp_function
cf
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
cpp_function
cf
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
...
@@ -1016,7 +1033,7 @@ private:
...
@@ -1016,7 +1033,7 @@ private:
/// Initialize holder object, variant 2: try to construct from existing holder object, if possible
/// Initialize holder object, variant 2: try to construct from existing holder object, if possible
template
<
typename
T
=
holder_type
,
template
<
typename
T
=
holder_type
,
typename
std
::
enable_if
<
std
::
is_copy_constructible
<
T
>
::
value
,
int
>
::
type
=
0
>
detail
::
enable_if
_t
<
std
::
is_copy_constructible
<
T
>
::
value
,
int
>
=
0
>
static
void
init_holder_helper
(
instance_type
*
inst
,
const
holder_type
*
holder_ptr
,
const
void
*
/* dummy */
)
{
static
void
init_holder_helper
(
instance_type
*
inst
,
const
holder_type
*
holder_ptr
,
const
void
*
/* dummy */
)
{
if
(
holder_ptr
)
if
(
holder_ptr
)
new
(
&
inst
->
holder
)
holder_type
(
*
holder_ptr
);
new
(
&
inst
->
holder
)
holder_type
(
*
holder_ptr
);
...
@@ -1026,7 +1043,7 @@ private:
...
@@ -1026,7 +1043,7 @@ private:
/// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer
/// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer
template
<
typename
T
=
holder_type
,
template
<
typename
T
=
holder_type
,
typename
std
::
enable_if
<!
std
::
is_copy_constructible
<
T
>
::
value
,
int
>
::
type
=
0
>
detail
::
enable_if
_t
<!
std
::
is_copy_constructible
<
T
>
::
value
,
int
>
=
0
>
static
void
init_holder_helper
(
instance_type
*
inst
,
const
holder_type
*
/* unused */
,
const
void
*
/* dummy */
)
{
static
void
init_holder_helper
(
instance_type
*
inst
,
const
holder_type
*
/* unused */
,
const
void
*
/* dummy */
)
{
new
(
&
inst
->
holder
)
holder_type
(
inst
->
value
);
new
(
&
inst
->
holder
)
holder_type
(
inst
->
value
);
}
}
...
@@ -1196,7 +1213,7 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
...
@@ -1196,7 +1213,7 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
iterator
make_iterator
(
Iterator
first
,
Sentinel
last
,
Extra
&&
...
extra
)
{
iterator
make_iterator
(
Iterator
first
,
Sentinel
last
,
Extra
&&
...
extra
)
{
typedef
detail
::
iterator_state
<
Iterator
,
Sentinel
,
false
,
Policy
>
state
;
typedef
detail
::
iterator_state
<
Iterator
,
Sentinel
,
false
,
Policy
>
state
;
if
(
!
detail
::
get_type_info
(
typeid
(
state
)))
{
if
(
!
detail
::
get_type_info
(
typeid
(
state
)
,
false
))
{
class_
<
state
>
(
handle
(),
"iterator"
)
class_
<
state
>
(
handle
(),
"iterator"
)
.
def
(
"__iter__"
,
[](
state
&
s
)
->
state
&
{
return
s
;
})
.
def
(
"__iter__"
,
[](
state
&
s
)
->
state
&
{
return
s
;
})
.
def
(
"__next__"
,
[](
state
&
s
)
->
ValueType
{
.
def
(
"__next__"
,
[](
state
&
s
)
->
ValueType
{
...
@@ -1221,7 +1238,7 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
...
@@ -1221,7 +1238,7 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
iterator
make_key_iterator
(
Iterator
first
,
Sentinel
last
,
Extra
&&
...
extra
)
{
iterator
make_key_iterator
(
Iterator
first
,
Sentinel
last
,
Extra
&&
...
extra
)
{
typedef
detail
::
iterator_state
<
Iterator
,
Sentinel
,
true
,
Policy
>
state
;
typedef
detail
::
iterator_state
<
Iterator
,
Sentinel
,
true
,
Policy
>
state
;
if
(
!
detail
::
get_type_info
(
typeid
(
state
)))
{
if
(
!
detail
::
get_type_info
(
typeid
(
state
)
,
false
))
{
class_
<
state
>
(
handle
(),
"iterator"
)
class_
<
state
>
(
handle
(),
"iterator"
)
.
def
(
"__iter__"
,
[](
state
&
s
)
->
state
&
{
return
s
;
})
.
def
(
"__iter__"
,
[](
state
&
s
)
->
state
&
{
return
s
;
})
.
def
(
"__next__"
,
[](
state
&
s
)
->
KeyType
{
.
def
(
"__next__"
,
[](
state
&
s
)
->
KeyType
{
...
...
include/pybind11/pytypes.h
View file @
d922dffe
...
@@ -43,10 +43,8 @@ public:
...
@@ -43,10 +43,8 @@ public:
bool
is_none
()
const
{
return
m_ptr
==
Py_None
;
}
bool
is_none
()
const
{
return
m_ptr
==
Py_None
;
}
template
<
typename
T
>
T
cast
()
const
;
template
<
typename
T
>
T
cast
()
const
;
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
#if __cplusplus > 201103L
PYBIND11_DEPRECATED
(
"call(...) was deprecated in favor of operator()(...)"
)
[[
deprecated
(
"call(...) was deprecated in favor of operator()(...)"
)]]
object
call
(
Args
&&
...
args
)
const
;
#endif
object
call
(
Args
&&
...
args
)
const
;
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
object
operator
()(
Args
&&
...
args
)
const
;
object
operator
()(
Args
&&
...
args
)
const
;
operator
bool
()
const
{
return
m_ptr
!=
nullptr
;
}
operator
bool
()
const
{
return
m_ptr
!=
nullptr
;
}
...
@@ -492,7 +490,7 @@ class int_ : public object {
...
@@ -492,7 +490,7 @@ class int_ : public object {
public:
public:
PYBIND11_OBJECT_DEFAULT
(
int_
,
object
,
PYBIND11_LONG_CHECK
)
PYBIND11_OBJECT_DEFAULT
(
int_
,
object
,
PYBIND11_LONG_CHECK
)
template
<
typename
T
,
template
<
typename
T
,
typename
std
::
enable_if
<
std
::
is_integral
<
T
>
::
value
,
int
>
::
type
=
0
>
detail
::
enable_if
_t
<
std
::
is_integral
<
T
>
::
value
,
int
>
=
0
>
int_
(
T
value
)
{
int_
(
T
value
)
{
if
(
sizeof
(
T
)
<=
sizeof
(
long
))
{
if
(
sizeof
(
T
)
<=
sizeof
(
long
))
{
if
(
std
::
is_signed
<
T
>::
value
)
if
(
std
::
is_signed
<
T
>::
value
)
...
@@ -509,7 +507,7 @@ public:
...
@@ -509,7 +507,7 @@ public:
}
}
template
<
typename
T
,
template
<
typename
T
,
typename
std
::
enable_if
<
std
::
is_integral
<
T
>
::
value
,
int
>
::
type
=
0
>
detail
::
enable_if
_t
<
std
::
is_integral
<
T
>
::
value
,
int
>
=
0
>
operator
T
()
const
{
operator
T
()
const
{
if
(
sizeof
(
T
)
<=
sizeof
(
long
))
{
if
(
sizeof
(
T
)
<=
sizeof
(
long
))
{
if
(
std
::
is_signed
<
T
>::
value
)
if
(
std
::
is_signed
<
T
>::
value
)
...
@@ -614,7 +612,7 @@ public:
...
@@ -614,7 +612,7 @@ public:
}
}
size_t
size
()
const
{
return
(
size_t
)
PyList_Size
(
m_ptr
);
}
size_t
size
()
const
{
return
(
size_t
)
PyList_Size
(
m_ptr
);
}
detail
::
list_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
list_accessor
(
*
this
,
index
);
}
detail
::
list_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
list_accessor
(
*
this
,
index
);
}
void
append
(
const
object
&
object
)
const
{
PyList_Append
(
m_ptr
,
object
.
ptr
());
}
void
append
(
handle
h
)
const
{
PyList_Append
(
m_ptr
,
h
.
ptr
());
}
};
};
class
args
:
public
tuple
{
PYBIND11_OBJECT_DEFAULT
(
args
,
tuple
,
PyTuple_Check
)
};
class
args
:
public
tuple
{
PYBIND11_OBJECT_DEFAULT
(
args
,
tuple
,
PyTuple_Check
)
};
...
...
include/pybind11/stl.h
View file @
d922dffe
...
@@ -112,7 +112,7 @@ template <typename Type, typename Value> struct list_caster {
...
@@ -112,7 +112,7 @@ template <typename Type, typename Value> struct list_caster {
}
}
template
<
typename
T
=
Type
,
template
<
typename
T
=
Type
,
typename
std
::
enable_if
<
std
::
is_same
<
decltype
(
std
::
declval
<
T
>().
reserve
(
0
)),
void
>::
value
,
int
>
::
type
=
0
>
enable_if
_t
<
std
::
is_same
<
decltype
(
std
::
declval
<
T
>().
reserve
(
0
)),
void
>::
value
,
int
>
=
0
>
void
reserve_maybe
(
list
l
,
Type
*
)
{
value
.
reserve
(
l
.
size
());
}
void
reserve_maybe
(
list
l
,
Type
*
)
{
value
.
reserve
(
l
.
size
());
}
void
reserve_maybe
(
list
,
void
*
)
{
}
void
reserve_maybe
(
list
,
void
*
)
{
}
...
...
include/pybind11/stl_bind.h
View file @
d922dffe
...
@@ -12,8 +12,6 @@
...
@@ -12,8 +12,6 @@
#include "common.h"
#include "common.h"
#include "operators.h"
#include "operators.h"
#include <type_traits>
#include <utility>
#include <algorithm>
#include <algorithm>
#include <sstream>
#include <sstream>
...
@@ -42,20 +40,20 @@ struct is_comparable : std::false_type { };
...
@@ -42,20 +40,20 @@ struct is_comparable : std::false_type { };
/* For non-map data structures, check whether operator== can be instantiated */
/* For non-map data structures, check whether operator== can be instantiated */
template
<
typename
T
>
template
<
typename
T
>
struct
is_comparable
<
struct
is_comparable
<
T
,
typename
std
::
enable_if
<
container_traits
<
T
>::
is_element
&&
T
,
enable_if
_t
<
container_traits
<
T
>::
is_element
&&
container_traits
<
T
>::
is_comparable
>
::
type
>
container_traits
<
T
>::
is_comparable
>>
:
std
::
true_type
{
};
:
std
::
true_type
{
};
/* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */
/* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */
template
<
typename
T
>
template
<
typename
T
>
struct
is_comparable
<
T
,
typename
std
::
enable_if
<
container_traits
<
T
>::
is_vector
>
::
type
>
{
struct
is_comparable
<
T
,
enable_if
_t
<
container_traits
<
T
>::
is_vector
>>
{
static
constexpr
const
bool
value
=
static
constexpr
const
bool
value
=
is_comparable
<
typename
T
::
value_type
>::
value
;
is_comparable
<
typename
T
::
value_type
>::
value
;
};
};
/* For pairs, recursively check the two data types */
/* For pairs, recursively check the two data types */
template
<
typename
T
>
template
<
typename
T
>
struct
is_comparable
<
T
,
typename
std
::
enable_if
<
container_traits
<
T
>::
is_pair
>
::
type
>
{
struct
is_comparable
<
T
,
enable_if
_t
<
container_traits
<
T
>::
is_pair
>>
{
static
constexpr
const
bool
value
=
static
constexpr
const
bool
value
=
is_comparable
<
typename
T
::
first_type
>::
value
&&
is_comparable
<
typename
T
::
first_type
>::
value
&&
is_comparable
<
typename
T
::
second_type
>::
value
;
is_comparable
<
typename
T
::
second_type
>::
value
;
...
@@ -66,13 +64,13 @@ template <typename, typename, typename... Args> void vector_if_copy_constructibl
...
@@ -66,13 +64,13 @@ template <typename, typename, typename... Args> void vector_if_copy_constructibl
template
<
typename
,
typename
,
typename
...
Args
>
void
vector_if_equal_operator
(
const
Args
&
...)
{
}
template
<
typename
,
typename
,
typename
...
Args
>
void
vector_if_equal_operator
(
const
Args
&
...)
{
}
template
<
typename
,
typename
,
typename
...
Args
>
void
vector_if_insertion_operator
(
const
Args
&
...)
{
}
template
<
typename
,
typename
,
typename
...
Args
>
void
vector_if_insertion_operator
(
const
Args
&
...)
{
}
template
<
typename
Vector
,
typename
Class_
,
typename
std
::
enable_if
<
std
::
is_copy_constructible
<
typename
Vector
::
value_type
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
Vector
,
typename
Class_
,
enable_if
_t
<
std
::
is_copy_constructible
<
typename
Vector
::
value_type
>
::
value
,
int
>
=
0
>
void
vector_if_copy_constructible
(
Class_
&
cl
)
{
void
vector_if_copy_constructible
(
Class_
&
cl
)
{
cl
.
def
(
pybind11
::
init
<
const
Vector
&>
(),
cl
.
def
(
pybind11
::
init
<
const
Vector
&>
(),
"Copy constructor"
);
"Copy constructor"
);
}
}
template
<
typename
Vector
,
typename
Class_
,
typename
std
::
enable_if
<
is_comparable
<
Vector
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
Vector
,
typename
Class_
,
enable_if
_t
<
is_comparable
<
Vector
>
::
value
,
int
>
=
0
>
void
vector_if_equal_operator
(
Class_
&
cl
)
{
void
vector_if_equal_operator
(
Class_
&
cl
)
{
using
T
=
typename
Vector
::
value_type
;
using
T
=
typename
Vector
::
value_type
;
...
@@ -378,7 +376,7 @@ template <typename Map, typename Class_, typename... Args> void map_if_copy_assi
...
@@ -378,7 +376,7 @@ template <typename Map, typename Class_, typename... Args> void map_if_copy_assi
);
);
}
}
template
<
typename
Map
,
typename
Class_
,
typename
std
::
enable_if
<!
std
::
is_copy_assignable
<
typename
Map
::
mapped_type
>
::
value
,
int
>
::
type
=
0
>
template
<
typename
Map
,
typename
Class_
,
enable_if
_t
<!
std
::
is_copy_assignable
<
typename
Map
::
mapped_type
>
::
value
,
int
>
=
0
>
void
map_if_copy_assignable
(
Class_
&
cl
)
{
void
map_if_copy_assignable
(
Class_
&
cl
)
{
using
KeyType
=
typename
Map
::
key_type
;
using
KeyType
=
typename
Map
::
key_type
;
using
MappedType
=
typename
Map
::
mapped_type
;
using
MappedType
=
typename
Map
::
mapped_type
;
...
...
tests/CMakeLists.txt
View file @
d922dffe
...
@@ -29,9 +29,9 @@ set(PYBIND11_TEST_FILES
...
@@ -29,9 +29,9 @@ set(PYBIND11_TEST_FILES
test_pickling.cpp
test_pickling.cpp
test_python_types.cpp
test_python_types.cpp
test_sequences_and_iterators.cpp
test_sequences_and_iterators.cpp
test_smart_ptr.cpp
test_stl_binders.cpp
test_stl_binders.cpp
test_virtual_functions.cpp
test_virtual_functions.cpp
test_multiple_inheritance.cpp
)
)
string
(
REPLACE
".cpp"
".py"
PYBIND11_PYTEST_FILES
"
${
PYBIND11_TEST_FILES
}
"
)
string
(
REPLACE
".cpp"
".py"
PYBIND11_PYTEST_FILES
"
${
PYBIND11_TEST_FILES
}
"
)
...
...
tests/test_callbacks.py
View file @
d922dffe
...
@@ -83,7 +83,7 @@ def test_cpp_function_roundtrip():
...
@@ -83,7 +83,7 @@ def test_cpp_function_roundtrip():
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
test_dummy_function
(
dummy_function2
)
test_dummy_function
(
dummy_function2
)
assert
"
I
ncompatible function arguments"
in
str
(
excinfo
.
value
)
assert
"
i
ncompatible function arguments"
in
str
(
excinfo
.
value
)
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
test_dummy_function
(
lambda
x
,
y
:
x
+
y
)
test_dummy_function
(
lambda
x
,
y
:
x
+
y
)
...
...
tests/test_inheritance.cpp
View file @
d922dffe
...
@@ -61,7 +61,7 @@ test_initializer inheritance([](py::module &m) {
...
@@ -61,7 +61,7 @@ test_initializer inheritance([](py::module &m) {
.
def
(
py
::
init
<
std
::
string
>
());
.
def
(
py
::
init
<
std
::
string
>
());
/* Another way of declaring a subclass relationship: reference parent's C++ type */
/* Another way of declaring a subclass relationship: reference parent's C++ type */
py
::
class_
<
Rabbit
>
(
m
,
"Rabbit"
,
py
::
base
<
Pet
>
()
)
py
::
class_
<
Rabbit
,
Pet
>
(
m
,
"Rabbit"
)
.
def
(
py
::
init
<
std
::
string
>
());
.
def
(
py
::
init
<
std
::
string
>
());
/* And another: list parent in class template arguments */
/* And another: list parent in class template arguments */
...
...
tests/test_inheritance.py
View file @
d922dffe
...
@@ -24,9 +24,10 @@ def test_inheritance(msg):
...
@@ -24,9 +24,10 @@ def test_inheritance(msg):
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
dog_bark
(
polly
)
dog_bark
(
polly
)
assert
msg
(
excinfo
.
value
)
==
"""
assert
msg
(
excinfo
.
value
)
==
"""
I
ncompatible function arguments. The following argument types are supported:
dog_bark(): i
ncompatible function arguments. The following argument types are supported:
1. (arg0: m.Dog) -> str
1. (arg0: m.Dog) -> str
Invoked with: <m.Pet object at 0>
Invoked with: <m.Pet object at 0>
"""
"""
...
...
Prev
1
2
Next
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