// file x.h
struct X {
  int data;
};


// file y.h
#include <cstddef>
#include <type_traits>

class Y {
public:
  Y();
  ~Y();
  /*...*/
private:
  static const size_t sizeofx = 8;
  static const size_t alignofx = 4;

  std::aligned_storage<sizeofx, alignofx>::type _x;
};

// file y.cpp
#include <new>
//#include "y.h"
//#include "x.h"

Y::Y() {
  // compile-time checks
  static_assert(sizeofx  >= sizeof(X),  "sizeofx too small");
  static_assert(alignofx == alignof(X), "alignofx is incorrect");
  // does not allocate memory, but constructs an object at &_x
  new (&_x) X;
}

Y::~Y() {
  (reinterpret_cast<X*>(&_x))->~X();
}


// file main.cpp
//#include "y.h"

int main()
{
  Y y;
  return 0;
}