Refactoring had_equal_operator so it now can handle STL containers which have operator== always defined. Adding specialization for vector, deque, set, pair and map types.

This commit is contained in:
Sergey Lyskov 2016-05-12 18:17:02 -04:00
parent 26a49b9b35
commit b82c0ea164
3 changed files with 42 additions and 26 deletions

View File

@ -34,4 +34,6 @@ void init_ex17(py::module &m) {
pybind11::vector_binder<int>(m, "VectorInt"); pybind11::vector_binder<int>(m, "VectorInt");
pybind11::vector_binder<A>(m, "VectorA"); pybind11::vector_binder<A>(m, "VectorA");
pybind11::vector_binder< std::vector<A> >(m, "VectorVectorA");
} }

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from __future__ import print_function from __future__ import print_function
from example import VectorInt, VectorA, A from example import VectorInt, A, VectorA, VectorVectorA
v_int = VectorInt(2) v_int = VectorInt(2)
print(len(v_int)) print(len(v_int))
@ -29,3 +29,6 @@ v_a = VectorA()
v_a.append(A(1)) v_a.append(A(1))
v_a.append(A(2)) v_a.append(A(2))
print(v_a) print(v_a)
vv_a = VectorVectorA()
vv_a.append(v_a)

View File

@ -17,33 +17,52 @@
#include <utility> #include <utility>
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
#include <vector>
#include <map>
#include <set>
#include <deque>
NAMESPACE_BEGIN(pybind11) NAMESPACE_BEGIN(pybind11)
NAMESPACE_BEGIN(detail) NAMESPACE_BEGIN(detail)
template<typename T> template<typename T>
constexpr auto has_equal_operator(int) -> decltype(std::declval<T>() == std::declval<T>(), bool()) { return true; } constexpr auto has_equal_operator(int) -> decltype(std::declval<T>() == std::declval<T>(), std::declval<T>() != std::declval<T>(), bool()) { return true; }
template<typename T> template<typename T>
constexpr bool has_equal_operator(...) { return false; } constexpr bool has_equal_operator(...) { return false; }
// Workaround for MSVC 2015 template<typename T, typename SFINAE = void>
template<typename T>
struct has_equal_operator_s { struct has_equal_operator_s {
static const bool value = false;
};
template<typename T>
struct has_equal_operator_s<T>
{
static const bool value = has_equal_operator<T>(0); static const bool value = has_equal_operator<T>(0);
}; };
template<> template <typename A>
struct has_equal_operator_s< std::vector<A> >
{
template<typename T> static const bool value = has_equal_operator_s<A>::value;
constexpr auto has_not_equal_operator(int) -> decltype(std::declval<T>() != std::declval<T>(), bool()) { return true; } };
template<typename T> template<> template <typename A>
constexpr bool has_not_equal_operator(...) { return false; } struct has_equal_operator_s< std::deque<A> >
{
// Workaround for MSVC 2015 static const bool value = has_equal_operator_s<A>::value;
template<typename T> };
struct has_not_equal_operator_s { template<> template <typename A>
static const bool value = has_not_equal_operator<T>(0); struct has_equal_operator_s< std::set<A> >
{
static const bool value = has_equal_operator_s<A>::value;
};
template<> template <typename A, typename B>
struct has_equal_operator_s< std::pair<A,B> >
{
static const bool value = has_equal_operator_s<A>::value and has_equal_operator_s<B>::value;
};
template<> template <typename A, typename B>
struct has_equal_operator_s< std::map<A,B> >
{
static const bool value = has_equal_operator_s<A>::value and has_equal_operator_s<B>::value;
}; };
@ -103,6 +122,7 @@ void vector_maybe_has_equal_operator(Class_ &cl) {
using T = typename Vector::value_type; using T = typename Vector::value_type;
cl.def(pybind11::self == pybind11::self); cl.def(pybind11::self == pybind11::self);
cl.def(pybind11::self != pybind11::self);
cl.def("count", [](Vector const &v, T const & value) { return std::count(v.begin(), v.end(), value); }, "counts the elements that are equal to value"); cl.def("count", [](Vector const &v, T const & value) { return std::count(v.begin(), v.end(), value); }, "counts the elements that are equal to value");
@ -118,14 +138,6 @@ template<typename Vector, typename Class_, typename std::enable_if< !has_equal_o
void vector_maybe_has_equal_operator(Class_ &) {} void vector_maybe_has_equal_operator(Class_ &) {}
template<typename Vector, typename Class_, typename std::enable_if< has_not_equal_operator_s<typename Vector::value_type>::value >::type * = nullptr>
void vector_maybe_has_not_equal_operator(Class_ &cl) {
cl.def(pybind11::self != pybind11::self);
}
template<typename Vector, typename Class_, typename std::enable_if< !has_not_equal_operator_s<typename Vector::value_type>::value >::type * = nullptr>
void vector_maybe_has_not_equal_operator(Class_ &) {}
template<typename Vector, typename Class_, typename std::enable_if< has_insertion_operator_s<typename Vector::value_type>::value >::type * = nullptr> template<typename Vector, typename Class_, typename std::enable_if< has_insertion_operator_s<typename Vector::value_type>::value >::type * = nullptr>
void vector_maybe_has_insertion_operator(char const *name, Class_ &cl) { void vector_maybe_has_insertion_operator(char const *name, Class_ &cl) {
using size_type = typename Vector::size_type; using size_type = typename Vector::size_type;
@ -244,7 +256,6 @@ pybind11::class_<std::vector<T, Allocator>, holder_type > vector_binder(pybind11
// Comparisons // Comparisons
detail::vector_maybe_has_equal_operator<Vector>(cl); detail::vector_maybe_has_equal_operator<Vector>(cl);
detail::vector_maybe_has_not_equal_operator<Vector>(cl);
// Printing // Printing
detail::vector_maybe_has_insertion_operator<Vector>(name, cl); detail::vector_maybe_has_insertion_operator<Vector>(name, cl);