stl.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "pybind11.h"
  2. #include <array>
  3. #include <vector>
  4. #include <list>
  5. #include <deque>
  6. #include <forward_list>
  7. #include <map>
  8. #include <unordered_map>
  9. namespace pybind11::impl {
  10. template <typename T, std::size_t N>
  11. struct type_caster<std::array<T, N>> {
  12. struct wrapper {
  13. std::array<T, N> container = {};
  14. operator std::array<T, N>&& () { return std::move(container); }
  15. };
  16. wrapper value;
  17. bool load(const handle& src, bool convert) {
  18. if(!isinstance<list>(src)) { return false; }
  19. auto list = src.cast<pybind11::list>();
  20. if(list.size() != N) { return false; }
  21. for(std::size_t i = 0; i < N; ++i) {
  22. type_caster<T> caster;
  23. if(!caster.load(list[i], convert)) { return false; }
  24. value.container[i] = caster.value;
  25. }
  26. return true;
  27. }
  28. template <typename U>
  29. static handle cast(U&& src, return_value_policy policy, handle parent) {
  30. auto list = pybind11::list();
  31. for(auto& item: src) {
  32. list.append(pybind11::cast(item, policy, parent));
  33. }
  34. return list;
  35. }
  36. };
  37. template <typename T>
  38. constexpr bool is_py_list_like_v = false;
  39. template <typename T, typename Allocator>
  40. constexpr bool is_py_list_like_v<std::vector<T, Allocator>> = true;
  41. template <typename T, typename Allocator>
  42. constexpr bool is_py_list_like_v<std::list<T, Allocator>> = true;
  43. template <typename T, typename Allocator>
  44. constexpr bool is_py_list_like_v<std::deque<T, Allocator>> = true;
  45. template <typename T>
  46. struct type_caster<T, std::enable_if_t<is_py_list_like_v<T>>> {
  47. struct wrapper {
  48. T container;
  49. operator T&& () { return std::move(container); }
  50. };
  51. wrapper value;
  52. bool load(const handle& src, bool convert) {
  53. if(!isinstance<list>(src)) { return false; }
  54. auto list = src.cast<pybind11::list>();
  55. for(auto item: list) {
  56. type_caster<typename T::value_type> caster;
  57. if(!caster.load(item, convert)) { return false; }
  58. value.container.push_back(caster.value);
  59. }
  60. return true;
  61. }
  62. template <typename U>
  63. static handle cast(U&& src, return_value_policy policy, handle parent) {
  64. auto list = pybind11::list();
  65. if constexpr(std::is_same_v<T, std::vector<bool>>) {
  66. for(auto item: src) {
  67. list.append(pybind11::cast(bool(item), policy, parent));
  68. }
  69. } else {
  70. for(auto& item: src) {
  71. list.append(pybind11::cast(item, policy, parent));
  72. }
  73. }
  74. return list;
  75. }
  76. };
  77. template <typename T>
  78. constexpr bool is_py_map_like_v = false;
  79. template <typename Key, typename T, typename Compare, typename Allocator>
  80. constexpr bool is_py_map_like_v<std::map<Key, T, Compare, Allocator>> = true;
  81. template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
  82. constexpr bool is_py_map_like_v<std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> = true;
  83. template <typename T>
  84. struct type_caster<T, std::enable_if_t<is_py_map_like_v<T>>> {
  85. struct wrapper {
  86. T container;
  87. operator T&& () { return std::move(container); }
  88. };
  89. wrapper value;
  90. bool load(const handle& src, bool convert) {
  91. if(!isinstance<dict>(src)) { return false; }
  92. auto dict = src.cast<pybind11::dict>();
  93. for(auto item: dict) {
  94. type_caster<typename T::key_type> key_caster;
  95. if(!key_caster.load(item.first, convert)) { return false; }
  96. type_caster<typename T::mapped_type> value_caster;
  97. if(!value_caster.load(item.second, convert)) { return false; }
  98. value.container.try_emplace(key_caster.value, value_caster.value);
  99. }
  100. return true;
  101. }
  102. template <typename U>
  103. static handle cast(U&& src, return_value_policy policy, handle parent) {
  104. auto dict = pybind11::dict();
  105. for(auto& [key, value]: src) {
  106. dict[pybind11::cast(key, policy, parent)] = pybind11::cast(value, policy, parent);
  107. }
  108. return dict;
  109. }
  110. };
  111. } // namespace pybind11::impl