Skip to content

Commit 5c7e77c

Browse files
committed
Add odr_guard_registry() used in type_caster_odr_guard() default constructor.
1 parent c84f381 commit 5c7e77c

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

include/pybind11/cast.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
#include <iterator>
2525
#include <memory>
2626
#include <string>
27+
#include <system_error>
2728
#include <tuple>
2829
#include <type_traits>
30+
#include <typeindex>
31+
#include <unordered_map>
2932
#include <utility>
3033
#include <vector>
3134

@@ -44,8 +47,26 @@ class type_caster_for_class_ : public type_caster_base<T> {};
4447
template <typename type, typename SFINAE = void>
4548
class type_caster : public type_caster_for_class_<type> {};
4649

50+
inline std::unordered_map<std::type_index, std::type_index> &odr_guard_registry() {
51+
static std::unordered_map<std::type_index, std::type_index> reg;
52+
return reg;
53+
}
54+
4755
template <typename IntrinsicType>
48-
struct type_caster_odr_guard : type_caster<IntrinsicType> {};
56+
struct type_caster_odr_guard : type_caster<IntrinsicType> {
57+
type_caster_odr_guard() {
58+
auto it_ti = std::type_index(typeid(IntrinsicType));
59+
auto tc_ti = std::type_index(typeid(type_caster<IntrinsicType>));
60+
auto match = odr_guard_registry().find(it_ti);
61+
if (match == odr_guard_registry().end()) {
62+
odr_guard_registry().insert({it_ti, tc_ti});
63+
} else if (match->second != tc_ti) {
64+
throw std::system_error(std::make_error_code(std::errc::state_not_recoverable),
65+
"pybind11::detail::type_caster<" + type_id<IntrinsicType>()
66+
+ "> ODR VIOLATION DETECTED");
67+
}
68+
}
69+
};
4970

5071
template <typename type>
5172
using make_caster = type_caster_odr_guard<intrinsic_t<type>>;

0 commit comments

Comments
 (0)