stl.h 4.0 KB

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