#include <cstddef>
#include <utility>
//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 Klass, std::size_t size>
std::integral_constant<std::size_t, size> getPimplMemberType (char (Klass::*) [size]);
template <typename Klass, std::size_t size>
Klass getPimplKlassType (char (Klass::*) [size]);
template<auto StorageMember, typename PimplType>
constexpr void AlignCheck()
{
constexpr std::size_t Size = decltype(getPimplMemberType (StorageMember))::value;
using Implementer = decltype(getPimplKlassType (StorageMember));
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::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;
}