File indexing completed on 2025-01-18 10:17:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <pybind11/stl.h>
0011
0012 #include "constructor_stats.h"
0013 #include "pybind11_tests.h"
0014
0015 #ifndef PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL
0016 # define PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL
0017 #endif
0018 #include <pybind11/stl/filesystem.h>
0019
0020 #include <string>
0021 #include <vector>
0022
0023 #if defined(PYBIND11_TEST_BOOST)
0024 # include <boost/optional.hpp>
0025
0026 namespace PYBIND11_NAMESPACE {
0027 namespace detail {
0028 template <typename T>
0029 struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {};
0030
0031 template <>
0032 struct type_caster<boost::none_t> : void_caster<boost::none_t> {};
0033 }
0034 }
0035 #endif
0036
0037
0038 #if defined(PYBIND11_HAS_VARIANT)
0039 using std::variant;
0040 # define PYBIND11_TEST_VARIANT 1
0041 #elif defined(PYBIND11_TEST_BOOST)
0042 # include <boost/variant.hpp>
0043 # define PYBIND11_TEST_VARIANT 1
0044 using boost::variant;
0045
0046 namespace PYBIND11_NAMESPACE {
0047 namespace detail {
0048 template <typename... Ts>
0049 struct type_caster<boost::variant<Ts...>> : variant_caster<boost::variant<Ts...>> {};
0050
0051 template <>
0052 struct visit_helper<boost::variant> {
0053 template <typename... Args>
0054 static auto call(Args &&...args) -> decltype(boost::apply_visitor(args...)) {
0055 return boost::apply_visitor(args...);
0056 }
0057 };
0058 }
0059 }
0060 #endif
0061
0062 PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>);
0063
0064
0065 struct TplCtorClass {
0066 template <typename T>
0067 explicit TplCtorClass(const T &) {}
0068 bool operator==(const TplCtorClass &) const { return true; }
0069 };
0070
0071 namespace std {
0072 template <>
0073 struct hash<TplCtorClass> {
0074 size_t operator()(const TplCtorClass &) const { return 0; }
0075 };
0076 }
0077
0078 template <template <typename> class OptionalImpl, typename T>
0079 struct OptionalHolder {
0080
0081 OptionalHolder(){};
0082 bool member_initialized() const { return member && member->initialized; }
0083 OptionalImpl<T> member = T{};
0084 };
0085
0086 enum class EnumType {
0087 kSet = 42,
0088 kUnset = 85,
0089 };
0090
0091
0092
0093
0094
0095 template <template <typename> class OptionalImpl>
0096 class OptionalProperties {
0097 public:
0098 using OptionalEnumValue = OptionalImpl<EnumType>;
0099
0100 OptionalProperties() : value(EnumType::kSet) {}
0101 ~OptionalProperties() {
0102
0103
0104
0105 value = EnumType::kUnset;
0106 }
0107
0108 OptionalEnumValue &access_by_ref() { return value; }
0109 OptionalEnumValue access_by_copy() { return value; }
0110
0111 private:
0112 OptionalEnumValue value;
0113 };
0114
0115
0116
0117
0118
0119
0120
0121 template <typename T>
0122 class ReferenceSensitiveOptional {
0123 public:
0124 using value_type = T;
0125
0126 ReferenceSensitiveOptional() = default;
0127
0128 ReferenceSensitiveOptional(const T &value) : storage{value} {}
0129
0130 ReferenceSensitiveOptional(T &&value) : storage{std::move(value)} {}
0131 ReferenceSensitiveOptional &operator=(const T &value) {
0132 storage = {value};
0133 return *this;
0134 }
0135 ReferenceSensitiveOptional &operator=(T &&value) {
0136 storage = {std::move(value)};
0137 return *this;
0138 }
0139
0140 template <typename... Args>
0141 T &emplace(Args &&...args) {
0142 storage.clear();
0143 storage.emplace_back(std::forward<Args>(args)...);
0144 return storage.back();
0145 }
0146
0147 const T &value() const noexcept {
0148 assert(!storage.empty());
0149 return storage[0];
0150 }
0151
0152 const T &operator*() const noexcept { return value(); }
0153
0154 const T *operator->() const noexcept { return &value(); }
0155
0156 explicit operator bool() const noexcept { return !storage.empty(); }
0157
0158 private:
0159 std::vector<T> storage;
0160 };
0161
0162 namespace PYBIND11_NAMESPACE {
0163 namespace detail {
0164 template <typename T>
0165 struct type_caster<ReferenceSensitiveOptional<T>>
0166 : optional_caster<ReferenceSensitiveOptional<T>> {};
0167 }
0168 }
0169
0170 TEST_SUBMODULE(stl, m) {
0171
0172 m.def("cast_vector", []() { return std::vector<int>{1}; });
0173 m.def("load_vector", [](const std::vector<int> &v) { return v.at(0) == 1 && v.at(1) == 2; });
0174
0175 m.def("cast_bool_vector", []() { return std::vector<bool>{true, false}; });
0176 m.def("load_bool_vector",
0177 [](const std::vector<bool> &v) { return v.at(0) == true && v.at(1) == false; });
0178
0179 m.def(
0180 "cast_ptr_vector",
0181 []() {
0182
0183 static auto *v = new std::vector<RValueCaster>{2};
0184 return v;
0185 },
0186 py::return_value_policy::reference);
0187
0188
0189 m.def("cast_deque", []() { return std::deque<int>{1}; });
0190 m.def("load_deque", [](const std::deque<int> &v) { return v.at(0) == 1 && v.at(1) == 2; });
0191
0192
0193 m.def("cast_array", []() { return std::array<int, 2>{{1, 2}}; });
0194 m.def("load_array", [](const std::array<int, 2> &a) { return a[0] == 1 && a[1] == 2; });
0195
0196
0197 m.def("cast_valarray", []() { return std::valarray<int>{1, 4, 9}; });
0198 m.def("load_valarray", [](const std::valarray<int> &v) {
0199 return v.size() == 3 && v[0] == 1 && v[1] == 4 && v[2] == 9;
0200 });
0201
0202
0203 m.def("cast_map", []() { return std::map<std::string, std::string>{{"key", "value"}}; });
0204 m.def("load_map", [](const std::map<std::string, std::string> &map) {
0205 return map.at("key") == "value" && map.at("key2") == "value2";
0206 });
0207
0208
0209 m.def("cast_set", []() { return std::set<std::string>{"key1", "key2"}; });
0210 m.def("load_set", [](const std::set<std::string> &set) {
0211 return (set.count("key1") != 0u) && (set.count("key2") != 0u) && (set.count("key3") != 0u);
0212 });
0213
0214
0215 m.def("cast_rv_vector", []() { return std::vector<RValueCaster>{2}; });
0216 m.def("cast_rv_array", []() { return std::array<RValueCaster, 3>(); });
0217
0218
0219
0220 m.def("cast_rv_map", []() {
0221 return std::unordered_map<std::string, RValueCaster>{{"a", RValueCaster{}}};
0222 });
0223 m.def("cast_rv_nested", []() {
0224 std::vector<std::array<std::list<std::unordered_map<std::string, RValueCaster>>, 2>> v;
0225 v.emplace_back();
0226 v.back()[0].emplace_back();
0227 v.back()[0].back().emplace("b", RValueCaster{});
0228 v.back()[0].back().emplace("c", RValueCaster{});
0229 v.back()[1].emplace_back();
0230 v.back()[1].back().emplace("a", RValueCaster{});
0231 return v;
0232 });
0233 static std::array<RValueCaster, 2> lva;
0234 static std::unordered_map<std::string, RValueCaster> lvm{{"a", RValueCaster{}},
0235 {"b", RValueCaster{}}};
0236 static std::unordered_map<std::string, std::vector<std::list<std::array<RValueCaster, 2>>>>
0237 lvn;
0238 lvn["a"].emplace_back();
0239 lvn["a"].back().emplace_back();
0240 lvn["a"].emplace_back();
0241 lvn["a"].back().emplace_back();
0242 lvn["b"].emplace_back();
0243 lvn["b"].back().emplace_back();
0244 lvn["b"].back().emplace_back();
0245 static std::vector<RValueCaster> lvv{2};
0246 m.def("cast_lv_vector", []() -> const decltype(lvv) & { return lvv; });
0247 m.def("cast_lv_array", []() -> const decltype(lva) & { return lva; });
0248 m.def("cast_lv_map", []() -> const decltype(lvm) & { return lvm; });
0249 m.def("cast_lv_nested", []() -> const decltype(lvn) & { return lvn; });
0250
0251 m.def("cast_unique_ptr_vector", []() {
0252 std::vector<std::unique_ptr<UserType>> v;
0253 v.emplace_back(new UserType{7});
0254 v.emplace_back(new UserType{42});
0255 return v;
0256 });
0257
0258 pybind11::enum_<EnumType>(m, "EnumType")
0259 .value("kSet", EnumType::kSet)
0260 .value("kUnset", EnumType::kUnset);
0261
0262
0263 struct MoveOutContainer {
0264 struct Value {
0265 int value;
0266 };
0267 std::list<Value> move_list() const { return {{0}, {1}, {2}}; }
0268 };
0269 py::class_<MoveOutContainer::Value>(m, "MoveOutContainerValue")
0270 .def_readonly("value", &MoveOutContainer::Value::value);
0271 py::class_<MoveOutContainer>(m, "MoveOutContainer")
0272 .def(py::init<>())
0273 .def_property_readonly("move_list", &MoveOutContainer::move_list);
0274
0275
0276 struct NoAssign {
0277 int value;
0278
0279 explicit NoAssign(int value = 0) : value(value) {}
0280 NoAssign(const NoAssign &) = default;
0281 NoAssign(NoAssign &&) = default;
0282
0283 NoAssign &operator=(const NoAssign &) = delete;
0284 NoAssign &operator=(NoAssign &&) = delete;
0285 };
0286 py::class_<NoAssign>(m, "NoAssign", "Class with no C++ assignment operators")
0287 .def(py::init<>())
0288 .def(py::init<int>());
0289
0290 struct MoveOutDetector {
0291 MoveOutDetector() = default;
0292 MoveOutDetector(const MoveOutDetector &) = default;
0293 MoveOutDetector(MoveOutDetector &&other) noexcept : initialized(other.initialized) {
0294
0295 other.initialized = false;
0296 }
0297 bool initialized = true;
0298 };
0299 py::class_<MoveOutDetector>(m, "MoveOutDetector", "Class with move tracking")
0300 .def(py::init<>())
0301 .def_readonly("initialized", &MoveOutDetector::initialized);
0302
0303 #ifdef PYBIND11_HAS_OPTIONAL
0304
0305 m.attr("has_optional") = true;
0306
0307 using opt_int = std::optional<int>;
0308 using opt_no_assign = std::optional<NoAssign>;
0309 m.def("double_or_zero", [](const opt_int &x) -> int { return x.value_or(0) * 2; });
0310 m.def("half_or_none", [](int x) -> opt_int { return x != 0 ? opt_int(x / 2) : opt_int(); });
0311 m.def(
0312 "test_nullopt",
0313 [](opt_int x) { return x.value_or(42); },
0314 py::arg_v("x", std::nullopt, "None"));
0315 m.def(
0316 "test_no_assign",
0317 [](const opt_no_assign &x) { return x ? x->value : 42; },
0318 py::arg_v("x", std::nullopt, "None"));
0319
0320 m.def("nodefer_none_optional", [](std::optional<int>) { return true; });
0321 m.def("nodefer_none_optional", [](const py::none &) { return false; });
0322
0323 using opt_holder = OptionalHolder<std::optional, MoveOutDetector>;
0324 py::class_<opt_holder>(m, "OptionalHolder", "Class with optional member")
0325 .def(py::init<>())
0326 .def_readonly("member", &opt_holder::member)
0327 .def("member_initialized", &opt_holder::member_initialized);
0328
0329 using opt_props = OptionalProperties<std::optional>;
0330 pybind11::class_<opt_props>(m, "OptionalProperties")
0331 .def(pybind11::init<>())
0332 .def_property_readonly("access_by_ref", &opt_props::access_by_ref)
0333 .def_property_readonly("access_by_copy", &opt_props::access_by_copy);
0334 #endif
0335
0336 #ifdef PYBIND11_HAS_EXP_OPTIONAL
0337
0338 m.attr("has_exp_optional") = true;
0339
0340 using exp_opt_int = std::experimental::optional<int>;
0341 using exp_opt_no_assign = std::experimental::optional<NoAssign>;
0342 m.def("double_or_zero_exp", [](const exp_opt_int &x) -> int { return x.value_or(0) * 2; });
0343 m.def("half_or_none_exp",
0344 [](int x) -> exp_opt_int { return x ? exp_opt_int(x / 2) : exp_opt_int(); });
0345 m.def(
0346 "test_nullopt_exp",
0347 [](exp_opt_int x) { return x.value_or(42); },
0348 py::arg_v("x", std::experimental::nullopt, "None"));
0349 m.def(
0350 "test_no_assign_exp",
0351 [](const exp_opt_no_assign &x) { return x ? x->value : 42; },
0352 py::arg_v("x", std::experimental::nullopt, "None"));
0353
0354 using opt_exp_holder = OptionalHolder<std::experimental::optional, MoveOutDetector>;
0355 py::class_<opt_exp_holder>(m, "OptionalExpHolder", "Class with optional member")
0356 .def(py::init<>())
0357 .def_readonly("member", &opt_exp_holder::member)
0358 .def("member_initialized", &opt_exp_holder::member_initialized);
0359
0360 using opt_exp_props = OptionalProperties<std::experimental::optional>;
0361 pybind11::class_<opt_exp_props>(m, "OptionalExpProperties")
0362 .def(pybind11::init<>())
0363 .def_property_readonly("access_by_ref", &opt_exp_props::access_by_ref)
0364 .def_property_readonly("access_by_copy", &opt_exp_props::access_by_copy);
0365 #endif
0366
0367 #if defined(PYBIND11_TEST_BOOST)
0368
0369 m.attr("has_boost_optional") = true;
0370
0371 using boost_opt_int = boost::optional<int>;
0372 using boost_opt_no_assign = boost::optional<NoAssign>;
0373 m.def("double_or_zero_boost", [](const boost_opt_int &x) -> int { return x.value_or(0) * 2; });
0374 m.def("half_or_none_boost",
0375 [](int x) -> boost_opt_int { return x != 0 ? boost_opt_int(x / 2) : boost_opt_int(); });
0376 m.def(
0377 "test_nullopt_boost",
0378 [](boost_opt_int x) { return x.value_or(42); },
0379 py::arg_v("x", boost::none, "None"));
0380 m.def(
0381 "test_no_assign_boost",
0382 [](const boost_opt_no_assign &x) { return x ? x->value : 42; },
0383 py::arg_v("x", boost::none, "None"));
0384
0385 using opt_boost_holder = OptionalHolder<boost::optional, MoveOutDetector>;
0386 py::class_<opt_boost_holder>(m, "OptionalBoostHolder", "Class with optional member")
0387 .def(py::init<>())
0388 .def_readonly("member", &opt_boost_holder::member)
0389 .def("member_initialized", &opt_boost_holder::member_initialized);
0390
0391 using opt_boost_props = OptionalProperties<boost::optional>;
0392 pybind11::class_<opt_boost_props>(m, "OptionalBoostProperties")
0393 .def(pybind11::init<>())
0394 .def_property_readonly("access_by_ref", &opt_boost_props::access_by_ref)
0395 .def_property_readonly("access_by_copy", &opt_boost_props::access_by_copy);
0396 #endif
0397
0398
0399 using refsensitive_opt_int = ReferenceSensitiveOptional<int>;
0400 using refsensitive_opt_no_assign = ReferenceSensitiveOptional<NoAssign>;
0401 m.def("double_or_zero_refsensitive",
0402 [](const refsensitive_opt_int &x) -> int { return (x ? x.value() : 0) * 2; });
0403 m.def("half_or_none_refsensitive", [](int x) -> refsensitive_opt_int {
0404 return x != 0 ? refsensitive_opt_int(x / 2) : refsensitive_opt_int();
0405 });
0406 m.def(
0407 "test_nullopt_refsensitive",
0408
0409 [](refsensitive_opt_int x) { return x ? x.value() : 42; },
0410 py::arg_v("x", refsensitive_opt_int(), "None"));
0411 m.def(
0412 "test_no_assign_refsensitive",
0413 [](const refsensitive_opt_no_assign &x) { return x ? x->value : 42; },
0414 py::arg_v("x", refsensitive_opt_no_assign(), "None"));
0415
0416 using opt_refsensitive_holder = OptionalHolder<ReferenceSensitiveOptional, MoveOutDetector>;
0417 py::class_<opt_refsensitive_holder>(
0418 m, "OptionalRefSensitiveHolder", "Class with optional member")
0419 .def(py::init<>())
0420 .def_readonly("member", &opt_refsensitive_holder::member)
0421 .def("member_initialized", &opt_refsensitive_holder::member_initialized);
0422
0423 using opt_refsensitive_props = OptionalProperties<ReferenceSensitiveOptional>;
0424 pybind11::class_<opt_refsensitive_props>(m, "OptionalRefSensitiveProperties")
0425 .def(pybind11::init<>())
0426 .def_property_readonly("access_by_ref", &opt_refsensitive_props::access_by_ref)
0427 .def_property_readonly("access_by_copy", &opt_refsensitive_props::access_by_copy);
0428
0429 #ifdef PYBIND11_HAS_FILESYSTEM
0430
0431 m.attr("has_filesystem") = true;
0432 m.def("parent_path", [](const std::filesystem::path &p) { return p.parent_path(); });
0433 #endif
0434
0435 #ifdef PYBIND11_TEST_VARIANT
0436 static_assert(std::is_same<py::detail::variant_caster_visitor::result_type, py::handle>::value,
0437 "visitor::result_type is required by boost::variant in C++11 mode");
0438
0439 struct visitor {
0440 using result_type = const char *;
0441
0442 result_type operator()(int) { return "int"; }
0443 result_type operator()(const std::string &) { return "std::string"; }
0444 result_type operator()(double) { return "double"; }
0445 result_type operator()(std::nullptr_t) { return "std::nullptr_t"; }
0446 # if defined(PYBIND11_HAS_VARIANT)
0447 result_type operator()(std::monostate) { return "std::monostate"; }
0448 # endif
0449 };
0450
0451
0452 m.def("load_variant", [](const variant<int, std::string, double, std::nullptr_t> &v) {
0453 return py::detail::visit_helper<variant>::call(visitor(), v);
0454 });
0455 m.def("load_variant_2pass", [](variant<double, int> v) {
0456 return py::detail::visit_helper<variant>::call(visitor(), v);
0457 });
0458 m.def("cast_variant", []() {
0459 using V = variant<int, std::string>;
0460 return py::make_tuple(V(5), V("Hello"));
0461 });
0462
0463 # if defined(PYBIND11_HAS_VARIANT)
0464
0465 m.def("load_monostate_variant",
0466 [](const variant<std::monostate, int, std::string> &v) -> const char * {
0467 return py::detail::visit_helper<variant>::call(visitor(), v);
0468 });
0469 m.def("cast_monostate_variant", []() {
0470 using V = variant<std::monostate, int, std::string>;
0471 return py::make_tuple(V{}, V(5), V("Hello"));
0472 });
0473 # endif
0474 #endif
0475
0476
0477
0478 m.def("tpl_ctor_vector", [](std::vector<TplCtorClass> &) {});
0479 m.def("tpl_ctor_map", [](std::unordered_map<TplCtorClass, TplCtorClass> &) {});
0480 m.def("tpl_ctor_set", [](std::unordered_set<TplCtorClass> &) {});
0481 #if defined(PYBIND11_HAS_OPTIONAL)
0482 m.def("tpl_constr_optional", [](std::optional<TplCtorClass> &) {});
0483 #endif
0484 #if defined(PYBIND11_HAS_EXP_OPTIONAL)
0485 m.def("tpl_constr_optional_exp", [](std::experimental::optional<TplCtorClass> &) {});
0486 #endif
0487 #if defined(PYBIND11_TEST_BOOST)
0488 m.def("tpl_constr_optional_boost", [](boost::optional<TplCtorClass> &) {});
0489 #endif
0490
0491
0492
0493 m.def("return_vec_of_reference_wrapper", [](std::reference_wrapper<UserType> p4) {
0494 static UserType p1{1}, p2{2}, p3{3};
0495 return std::vector<std::reference_wrapper<UserType>>{
0496 std::ref(p1), std::ref(p2), std::ref(p3), p4};
0497 });
0498
0499
0500 m.def(
0501 "stl_pass_by_pointer", [](std::vector<int> *v) { return *v; }, "v"_a = nullptr);
0502
0503
0504 m.def("func_with_string_or_vector_string_arg_overload",
0505 [](const std::vector<std::string> &) { return 1; });
0506 m.def("func_with_string_or_vector_string_arg_overload",
0507 [](const std::list<std::string> &) { return 2; });
0508 m.def("func_with_string_or_vector_string_arg_overload", [](const std::string &) { return 3; });
0509
0510 class Placeholder {
0511 public:
0512 Placeholder() { print_created(this); }
0513 Placeholder(const Placeholder &) = delete;
0514 ~Placeholder() { print_destroyed(this); }
0515 };
0516 py::class_<Placeholder>(m, "Placeholder");
0517
0518
0519 m.def(
0520 "test_stl_ownership",
0521 []() {
0522 std::vector<Placeholder *> result;
0523 result.push_back(new Placeholder());
0524 return result;
0525 },
0526 py::return_value_policy::take_ownership);
0527
0528 m.def("array_cast_sequence", [](std::array<int, 3> x) { return x; });
0529
0530
0531 struct Issue1561Inner {
0532 std::string data;
0533 };
0534 struct Issue1561Outer {
0535 std::vector<Issue1561Inner> list;
0536 };
0537
0538 py::class_<Issue1561Inner>(m, "Issue1561Inner")
0539 .def(py::init<std::string>())
0540 .def_readwrite("data", &Issue1561Inner::data);
0541
0542 py::class_<Issue1561Outer>(m, "Issue1561Outer")
0543 .def(py::init<>())
0544 .def_readwrite("list", &Issue1561Outer::list);
0545
0546 m.def(
0547 "return_vector_bool_raw_ptr",
0548 []() { return new std::vector<bool>(4513); },
0549
0550 py::return_value_policy::take_ownership);
0551 }