Skip to content

Instantly share code, notes, and snippets.

@bugaevc
Created July 6, 2020 13:38
Show Gist options
  • Save bugaevc/0cd4fd953cb1d02e188a4d6387b8491a to your computer and use it in GitHub Desktop.
Save bugaevc/0cd4fd953cb1d02e188a4d6387b8491a to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <type_traits>
#include <utility>
#include <new>
template<typename T>
void forget1(T &&value) {
union Forget {
~Forget() { }
typename std::remove_reference<T>::type t;
} u { std::move(value) };
}
template<typename T>
void forget2(T &&value) {
using U = typename std::remove_reference<T>::type;
char buffer[sizeof(U)];
new (buffer) U(std::move(value));
}
template<typename T>
T read(T *src) {
return T(std::move(*src));
}
template<typename T, typename U>
void write(T *dest, U &&src) {
new (dest) T(std::move(src));
}
template<typename T>
union MaybeUninit {
private:
T init;
public:
MaybeUninit() { }
MaybeUninit(T &&init) : init(std::move(init)) { }
~MaybeUninit() { }
operator const T *() const {
return &init;
}
operator T *() {
return &init;
}
T assume_init() && {
return std::move(init);
}
};
template<typename T>
T uninitialized() {
return MaybeUninit<T>().assume_init();
}
template<typename T>
T zeroed() {
char buffer[sizeof(T)] = { 0 };
return T(std::move(*reinterpret_cast<T *>(buffer)));
}
namespace demo {
static int next_loud_id = 0;
class Loud {
bool armed;
int id { next_loud_id++ };
public:
Loud() : armed(true) {
printf("Loud@%d()\n", id);
}
Loud(Loud &l) : armed(l.armed) {
printf("Loud@%d(Loud &@%d)\n", id, l.id);
}
Loud(Loud &&l) : armed(l.armed) {
l.armed = false;
printf("Loud@%d(Loud &&@%d)\n", id, l.id);
}
~Loud() {
printf("~Loud@%d(%sarmed)\n", id, armed ? "" : "dis");
}
};
void demo_forget1() {
printf("forget1:\n");
Loud loud;
forget1(loud);
}
void demo_forget2() {
printf("forget2:\n");
Loud loud;
forget2(loud);
}
void demo_read() {
printf("read:\n");
Loud loud1;
Loud loud2 = read(&loud1);
forget1(loud1);
}
void demo_write() {
printf("write:\n");
Loud loud;
write(&loud, Loud());
}
void demo_maybe_uninit() {
printf("MaybeUninit:\n");
MaybeUninit<Loud> maybe_loud;
write((Loud *) maybe_loud, Loud());
Loud loud = std::move(maybe_loud).assume_init();
}
void demo_uninitialized() {
printf("uninitialized:\n");
uninitialized<Loud>();
}
void demo_zeroed() {
printf("zeroed:\n");
zeroed<Loud>();
}
}
int main() {
demo::demo_forget1();
printf("\n");
demo::demo_forget2();
printf("\n");
demo::demo_read();
printf("\n");
demo::demo_write();
printf("\n");
demo::demo_maybe_uninit();
printf("\n");
demo::demo_uninitialized();
printf("\n");
demo::demo_zeroed();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment