#include <type_traits>
#include <iostream>
#include <cstring>
#include <memory>

template<typename T, typename U>
concept BitCastable = (sizeof(T) == sizeof(U)) && std::is_trivially_copyable_v<T> && std::is_trivially_copyable_v<U>;

template<typename U, BitCastable<U> T>
U bit_cast(const T& src)
{
    U dst;
    std::memcpy(&dst, &src, sizeof(T));
    return dst;
}

struct NonTriviallyCopyable
{
    int i;
    int i2;
    NonTriviallyCopyable() = default;
    NonTriviallyCopyable(const NonTriviallyCopyable&)
    {
        std::cout << "Copied!\n";
    }
};

int main()
{
    int x = 0;
    float y = bit_cast<float>(x);
    char storage[sizeof(NonTriviallyCopyable) - 4] __attribute__ ((aligned(alignof(NonTriviallyCopyable))));
    NonTriviallyCopyable ntc;
    static_assert(sizeof(ntc) != sizeof(storage));
    storage = bit_cast<decltype(storage)>(ntc);
    return 0;
}
