#include <iostream>
#include <vector>
#include <cstdint>

    template<class It>
    struct range_t {
      It b, e;
      It begin() const { return b; }
      It end() const { return e; }
      std::size_t size() const { return end()-begin(); }
    };

    template<class It>
    range_t<It> range(It s, It f) { return {s,f}; }

    template<class T>
    range_t< unsigned char* > as_bytes( T* t ) {
      static_assert( std::is_trivially_copyable<T>::value, "bad idea if not trivilaly copyable" );
      auto* ptr = reinterpret_cast<unsigned char*>(t);
      return range(ptr, ptr+sizeof(T));
    }
    template<class T>
    range_t< unsigned char const* > as_bytes( T const* t ) {
      static_assert( std::is_trivially_copyable<T>::value, "bad idea if not trivilaly copyable" );
      auto* ptr = reinterpret_cast<unsigned char const*>(t);
      return range(ptr, ptr+sizeof(T));
    }

    template<class T>
    void push_bytes_in( std::vector<std::uint8_t>& target, T const* data ) {
      auto bytes = as_bytes(data);
      target.insert( target.end(), bytes.begin(), bytes.end() );
    }
    template<class T>
    bool pop_bytes_out( std::vector<std::uint8_t>& src, T* data ) {
      auto bytes = as_bytes(data);
      if (bytes.size() > src.size()) return false;
      std::copy( src.end()-bytes.size(), src.end(), bytes.begin() );
      src.resize( src.size()-bytes.size() );
      return true;
    }
    
    struct some_data {
      int x, y;
      char buff[1024];
    };

   

int main() {
	std::vector<std::uint8_t> bytes;
	
	some_data data{1,2, "hello"};
	push_bytes_in( bytes, &data );
	some_data d2;
	if (!pop_bytes_out( bytes, &d2)) {
		std::cout << "failed\n";
		return -1;
	}
	std::cout << d2.buff << "\n";
}