#include <cstddef>
//von: https://thecppzoo.blogspot.com/2016/10/constexpr-offsetof-practical-way-to.html
namespace thecppzoo
{
//Frage: ist diese Implementierung frei von undefined behavior?
namespace detail {
template<typename T>
struct declval_helper { static T value; };
template<typename T, typename Z, Z T::*MPtr>
struct offset_helper {
using TV = declval_helper<T>;
char for_sizeof[(char *)&(TV::value.*MPtr) - (char *)&TV::value];
};
}
template<typename T, typename Z, Z T::*MPtr>
constexpr int offset_of() {
return sizeof(detail::offset_helper<T, Z, MPtr>::for_sizeof);
}
}
template<typename Implementer, std::size_t Size, char (Implementer::*StorageMember)[Size], typename PimplType>
constexpr void AlignCheck()
{
static_assert(Size == sizeof(PimplType), "wrong storage size");
constexpr int offset = thecppzoo::offset_of<Implementer, char[Size], StorageMember>();
constexpr size_t res = offset % alignof(PimplType);
static_assert(!res, "storage alignment wrong");
}
// >>> PimplHider.hpp
class PimplHider
{
public:
PimplHider();
private:
//char x; // einkommentieren erzeugt ein AlignCheck-static_assert, dann muesste man z.B. auf m_pimple_storage alignas(4) anwenden
char m_pimpl_storage[4]{};
};
// <<< end of PimplHider.hpp
// >>> PimpleHider.cpp
struct Pimpl
{
int pimple_stuff{0};
};
PimplHider::PimplHider()
{
// Funktioniert!
AlignCheck<PimplHider, sizeof(PimplHider::m_pimpl_storage), &PimplHider::m_pimpl_storage, Pimpl>();
//Fragen:
// ist diese verkürzte Schnittstelle irgendwie mit einem Template moeglich?
//AlignCheck<&PimplHider::m_pimpl_storage, Pimpl>();
// Anmerkung: Es definiert das der Storage immer ein char[n] sein muss
}
// <<< end of PimpleHider.cpp
int main()
{
return 0;
}