native_enum.h 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // Copyright (c) 2022-2025 The pybind Community.
  2. // All rights reserved. Use of this source code is governed by a
  3. // BSD-style license that can be found in the LICENSE file.
  4. #pragma once
  5. #include "detail/common.h"
  6. #include "detail/native_enum_data.h"
  7. #include "detail/type_caster_base.h"
  8. #include "cast.h"
  9. #include <cassert>
  10. #include <limits>
  11. #include <type_traits>
  12. #include <typeindex>
  13. PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
  14. /// Conversions between Python's native (stdlib) enum types and C++ enums.
  15. template <typename EnumType>
  16. class native_enum : public detail::native_enum_data {
  17. public:
  18. using Underlying = typename std::underlying_type<EnumType>::type;
  19. native_enum(const object &parent_scope,
  20. const char *name,
  21. const char *native_type_name,
  22. const char *class_doc = "")
  23. : detail::native_enum_data(
  24. parent_scope, name, native_type_name, class_doc, std::type_index(typeid(EnumType))) {
  25. if (detail::get_local_type_info(typeid(EnumType)) != nullptr
  26. || detail::get_global_type_info(typeid(EnumType)) != nullptr) {
  27. pybind11_fail(
  28. "pybind11::native_enum<...>(\"" + enum_name_encoded
  29. + "\") is already registered as a `pybind11::enum_` or `pybind11::class_`!");
  30. }
  31. if (detail::global_internals_native_enum_type_map_contains(enum_type_index)) {
  32. pybind11_fail("pybind11::native_enum<...>(\"" + enum_name_encoded
  33. + "\") is already registered!");
  34. }
  35. arm_finalize_check();
  36. }
  37. /// Export enumeration entries into the parent scope
  38. native_enum &export_values() {
  39. assert(!export_values_flag); // Catch redundant calls.
  40. export_values_flag = true;
  41. return *this;
  42. }
  43. /// Add an enumeration entry
  44. native_enum &value(char const *name, EnumType value, const char *doc = nullptr) {
  45. // Disarm for the case that the native_enum_data dtor runs during exception unwinding.
  46. disarm_finalize_check("value after finalize");
  47. members.append(make_tuple(name, static_cast<Underlying>(value)));
  48. if (doc) {
  49. member_docs.append(make_tuple(name, doc));
  50. }
  51. arm_finalize_check(); // There was no exception.
  52. return *this;
  53. }
  54. native_enum(const native_enum &) = delete;
  55. native_enum &operator=(const native_enum &) = delete;
  56. };
  57. PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)