admin管理员组文章数量:1291037
I have a CRTP-like construct:
class Derived : public Base<Derived>
I need to calculate a pointer to a Derived
object from a pointer to Base<Derived>
object via reinterpret_cast
. I cannot use dynamic_cast
because I'm not using virtual functions here.
The types are given, I do have the pointer to the Base<Derived>
object. I need the byte offset between the two types, so I can use reinterpret_cast
. How do I do this (without undefined behavior)? Is it possible to do at compile-time / save as a static constexpr
variable (I'm using C++20)?
I have a CRTP-like construct:
class Derived : public Base<Derived>
I need to calculate a pointer to a Derived
object from a pointer to Base<Derived>
object via reinterpret_cast
. I cannot use dynamic_cast
because I'm not using virtual functions here.
The types are given, I do have the pointer to the Base<Derived>
object. I need the byte offset between the two types, so I can use reinterpret_cast
. How do I do this (without undefined behavior)? Is it possible to do at compile-time / save as a static constexpr
variable (I'm using C++20)?
2 Answers
Reset to default 5There is no need for offset calculations or reinterpret_cast
.
If you are sure that the object is indeed a Derived
one, you can simply use static_cast
:
Derived derived;
Base<Derived> * pBase = &derived;
Derived * pDerived = static_cast<Derived*>(pBase);
Note that if pBase
above does not actually point to a Derived
object, using static_cast
in the last line will invoke undefined-behavior (UB).
A side note:
As @BenVoigt commented below, it is common to add a helper method to the CRTP base class that does exactly this cast.
I.e. add something like this to Base<Derived>
(replace Derived
if needed with the actual template parameter name in Base
):
template <typename Derived>
class Base {
Derived * ToDerived() { return static_cast<Derived*>(this); }
// ...
};
The CRTP pattern relies on a static_cast<> between the base class and the derived type. The Derived class type is the only derived class of the instantiated Base template type. Therefore it is guaranteed that a static_cast<Derived*>(this)
is safe within the template class Base. This is why it is common to see code such as:
template<class Derived> class Value {
protected:
Derived& derived() { return *static_cast<Derived*>(this); }
int& value() {
return derived().value(); // calls Derived::value()!
}
};
template<class Derived> class Inc : public Value<Derived> {
public:
int operator++ () {
this->value()++; // calls protected Value::value()!
return this->value();
}
int operator++ (int) {
auto r = this->value();
++this->value();
return r;
}
};
class obj : public Inc<obj> {
int x = 0;
public:
int& value() { return x; }
};
// class bad : public Inc<obj> {};
// wrong, Inc<obj> type is already an base class of obj
Here, class obj
only needs to implement the base class API value()
, for the intermediate base class Inc
to implement an pre and post increment operators for it.
(@wohlstad got the first answer so I thought to fill in a bit more detailed answer)
本文标签: cHow to tell the byte offset between a base class and a derived classStack Overflow
版权声明:本文标题:c++ - How to tell the byte offset between a base class and a derived class? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741517477a2382981.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
static_cast< Derived * >( pointer_to_base )
? – Richard Critten Commented Feb 13 at 16:32dynamic_cast
. My bad. – Newline Commented Feb 13 at 16:47dynamic_cast
with multiple or virtual inheritance – Caleth Commented Feb 13 at 17:03dynamic_cast<void*>(ptr);
. q.v. stackoverflow/a/4131099/4641116 (The other way around casting from a void pointer doesn't work.) – Eljay Commented Feb 13 at 17:19