I want to find a way to encapsulate a header-only 3rd party library without exposing its header files. In our other projects, we encapsulate by using void*
: in the implementation, we allocate memory and assign to it, and cast to pointer of its original type when we use it. But this time, the encapsulated class is used frequently, hence dynamic allocation is unacceptable. Here is another solution I'm currently considering.
Assuming that the encapsulated class need N bytes, I will make a char array member variable of size N in the wrapper class, named data
, for instance. In the implementation, when I try to assign an object of the encapsulated class to the wrapper, or forward a function call, I need to cast &data
to the pointer of encapsulated class by reinterpret_cast
, firstly. The char array is completely a placeholder. To make this clear, here is a sample code.
#include <iostream>
struct Inner {
void print() const {
std::cout << "Inner::print()\n";
}
};
struct Wrapper;
Inner* addressof(Wrapper&);
const Inner* addressof(const Wrapper&);
struct Wrapper {
Wrapper() {
Inner* ptr = addressof(*this);
*ptr = Inner();
}
void run() const {
addressof(*this)->print();
}
char data[1];
};
Inner* addressof(Wrapper& w) {
return reinterpret_cast<Inner*>(&(w.data));
}
const Inner* addressof(const Wrapper& w) {
return reinterpret_cast<const Inner*>(&(w.data));
}
int main() {
Wrapper wrp;
wrp.run();
}
From the view of memory, this seems make sense. But I'm sure if this is some kind of undefined behaviour.
Additionally, I want to know if there is a list of undefined behaviour. Seems like cppreference doesn't contain such thing and C++ standard specfication is really hard to understand.