-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate our assumption that the base class is a primary (offset-zero) base #213
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -340,6 +340,16 @@ class class_ : public object { | |
sizeof...(Ts) == !std::is_same_v<Base, T> + !std::is_same_v<Alias, T>, | ||
"nanobind::class_<> was invoked with extra arguments that could not be handled"); | ||
|
||
// Fail on virtual bases -- they need a this-ptr adjustment, but they're | ||
// not amenable to the runtime test in the class_ constructor (because | ||
// a C-style cast will do reinterpret_cast if static_cast is invalid). | ||
// Primary but inaccessible (ambiguous or private) bases will also | ||
// fail is_accessible_static_base_of; the !is_convertible option is to | ||
// avoid mis-detecting them as virtual bases. | ||
static_assert(!std::is_convertible_v<T*, Base*> || | ||
detail::is_accessible_static_base_of<Base, T>::value, | ||
"nanobind does not support virtual base classes"); | ||
|
||
template <typename... Extra> | ||
NB_INLINE class_(handle scope, const char *name, const Extra &... extra) { | ||
detail::type_init_data d; | ||
|
@@ -354,6 +364,13 @@ class class_ : public object { | |
if constexpr (!std::is_same_v<Base, T>) { | ||
d.base = &typeid(Base); | ||
d.flags |= (uint32_t) detail::type_init_flags::has_base; | ||
|
||
if (uintptr_t offset = (uintptr_t) (Base*) (T*) 0x1000 - 0x1000) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of the other operations in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately I'm not aware of any reasonable way to check the offset of a base class subobject at compile time. There is an unreasonable way:
But I think this is too heavyweight for nanobind; for example, it takes compilation time that's linear in the size of the bound class (although I haven't measured the constant factor).
Would changing the |
||
detail::raise("nanobind::class_<>: base class %s is at offset " | ||
"%td within %s! nanobind does not support " | ||
"multiple inheritance", typeid(Base).name(), | ||
offset, typeid(T).name()); | ||
} | ||
} | ||
|
||
if constexpr (!std::is_same_v<Alias, T>) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not do a
static_cast
and let that generate an error message then?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would break
nb::class_<Derived, Base>
where Base is a private or ambiguous base of Derived; in such a situation,is_base_of
is true butstatic_cast
doesn't work. Currently that works fine as long as Base is the primary base of Derived. If you don't think it's important to support non-public bases, then I agree that just usingstatic_cast
seems preferable.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should go out of our way to support non-public bases. In fact, the intention of such an interface is precisely to avoid the sort of
static_cast
that nanobind would otherwise perform when passingDerived
to functions expectingBase
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough! That should allow removing the virtual-base-specific checks.