mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
std::experimental::optional (#475)
* Add type caster for std::experimental::optional * Add tests for std::experimental::optional * Support both <optional> / <experimental/optional> * Mention std{::experimental,}::optional in the docs
This commit is contained in:
parent
bd560acf40
commit
44a69f78cf
@ -75,66 +75,70 @@ The following basic data types are supported out of the box (some may require
|
|||||||
an additional extension header to be included). To pass other data structures
|
an additional extension header to be included). To pass other data structures
|
||||||
as arguments and return values, refer to the section on binding :ref:`classes`.
|
as arguments and return values, refer to the section on binding :ref:`classes`.
|
||||||
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| Data type | Description | Header file |
|
| Data type | Description | Header file |
|
||||||
+=================================+==========================+===============================+
|
+=---================================+===========================+===============================+
|
||||||
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
| ``std::optional<T>`` | STL optional type (C++17) | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
| ``std::experimental::optional<T>`` | STL optional type (exp.) | :file:`pybind11/stl.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``std::chrono::time_point<...>``| STL date/time | :file:`pybind11/chrono.h` |
|
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
| ``std::chrono::time_point<...>`` | STL date/time | :file:`pybind11/chrono.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
|
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
||||||
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
|
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
||||||
|
+------------------------------------+---------------------------+-------------------------------+
|
||||||
|
@ -59,6 +59,7 @@ Breaking changes queued for v2.0.0 (Not yet released)
|
|||||||
to do it manually via ``PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)``.
|
to do it manually via ``PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)``.
|
||||||
* Default return values policy changes: non-static properties now use ``reference_internal``
|
* Default return values policy changes: non-static properties now use ``reference_internal``
|
||||||
and static properties use ``reference`` (previous default was ``automatic``, i.e. ``copy``).
|
and static properties use ``reference`` (previous default was ``automatic``, i.e. ``copy``).
|
||||||
|
* Support for ``std::experimental::optional<T>`` and ``std::optional<T>`` (C++17).
|
||||||
* Various minor improvements of library internals (no user-visible changes)
|
* Various minor improvements of library internals (no user-visible changes)
|
||||||
|
|
||||||
1.8.1 (July 12, 2016)
|
1.8.1 (July 12, 2016)
|
||||||
|
@ -22,6 +22,21 @@
|
|||||||
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __has_include
|
||||||
|
// std::optional
|
||||||
|
# if __has_include(<optional>)
|
||||||
|
# include <optional>
|
||||||
|
# define PYBIND11_HAS_OPTIONAL 1
|
||||||
|
# endif
|
||||||
|
// std::experimental::optional
|
||||||
|
# if __has_include(<experimental/optional>)
|
||||||
|
# include <experimental/optional>
|
||||||
|
# if __cpp_lib_experimental_optional // just in case
|
||||||
|
# define PYBIND11_HAS_EXP_OPTIONAL 1
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
NAMESPACE_BEGIN(pybind11)
|
NAMESPACE_BEGIN(pybind11)
|
||||||
NAMESPACE_BEGIN(detail)
|
NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
@ -183,6 +198,47 @@ template <typename Key, typename Value, typename Compare, typename Alloc> struct
|
|||||||
template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
|
template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
|
||||||
: map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { };
|
: map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { };
|
||||||
|
|
||||||
|
// This type caster is intended to be used for std::optional and std::experimental::optional
|
||||||
|
template<typename T> struct optional_caster {
|
||||||
|
using value_type = typename intrinsic_type<typename T::value_type>::type;
|
||||||
|
using caster_type = type_caster<value_type>;
|
||||||
|
|
||||||
|
static handle cast(const T& src, return_value_policy policy, handle parent) {
|
||||||
|
if (!src)
|
||||||
|
return none();
|
||||||
|
return caster_type::cast(*src, policy, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load(handle src, bool convert) {
|
||||||
|
if (!src) {
|
||||||
|
return false;
|
||||||
|
} else if (src.is_none()) {
|
||||||
|
value = {}; // nullopt
|
||||||
|
return true;
|
||||||
|
} else if (!inner.load(src, convert)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
value.emplace(static_cast<const value_type&>(inner));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_TYPE_CASTER(T, _("Optional[") + caster_type::name() + _("]"));
|
||||||
|
|
||||||
|
private:
|
||||||
|
caster_type inner;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if PYBIND11_HAS_OPTIONAL
|
||||||
|
template<typename T> struct type_caster<std::optional<T>>
|
||||||
|
: public optional_caster<std::optional<T>> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PYBIND11_HAS_EXP_OPTIONAL
|
||||||
|
template<typename T> struct type_caster<std::experimental::optional<T>>
|
||||||
|
: public optional_caster<std::experimental::optional<T>> {};
|
||||||
|
#endif
|
||||||
|
|
||||||
NAMESPACE_END(detail)
|
NAMESPACE_END(detail)
|
||||||
|
|
||||||
inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
|
inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
|
||||||
|
@ -289,4 +289,18 @@ test_initializer python_types([](py::module &m) {
|
|||||||
|
|
||||||
return d;
|
return d;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// this only tests std::experimental::optional for now
|
||||||
|
bool has_optional = false;
|
||||||
|
#ifdef PYBIND11_HAS_EXP_OPTIONAL
|
||||||
|
has_optional = true;
|
||||||
|
using opt_int = std::experimental::optional<int>;
|
||||||
|
m.def("double_or_zero", [](const opt_int& x) -> int {
|
||||||
|
return x.value_or(0) * 2;
|
||||||
|
});
|
||||||
|
m.def("half_or_none", [](int x) -> opt_int {
|
||||||
|
return x ? opt_int(x / 2) : opt_int();
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
m.attr("has_optional") = py::cast(has_optional);
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pybind11_tests import ExamplePythonTypes, ConstructorStats
|
from pybind11_tests import ExamplePythonTypes, ConstructorStats, has_optional
|
||||||
|
|
||||||
|
|
||||||
def test_static():
|
def test_static():
|
||||||
@ -295,3 +295,16 @@ def test_accessors():
|
|||||||
assert d["set"] == 1
|
assert d["set"] == 1
|
||||||
assert d["deferred_set"] == 1
|
assert d["deferred_set"] == 1
|
||||||
assert d["var"] == 99
|
assert d["var"] == 99
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not has_optional, reason='no <experimental/optional>')
|
||||||
|
def test_optional():
|
||||||
|
from pybind11_tests import double_or_zero, half_or_none
|
||||||
|
|
||||||
|
assert double_or_zero(None) == 0
|
||||||
|
assert double_or_zero(42) == 84
|
||||||
|
pytest.raises(TypeError, double_or_zero, 'foo')
|
||||||
|
|
||||||
|
assert half_or_none(0) is None
|
||||||
|
assert half_or_none(42) == 21
|
||||||
|
pytest.raises(TypeError, half_or_none, 'foo')
|
||||||
|
Loading…
Reference in New Issue
Block a user