-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexplicit_typesafe_raii.cpp
70 lines (60 loc) · 1.77 KB
/
explicit_typesafe_raii.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//
// Bad idea credit: Me
//
// Purpose: RAII can be very confusing when reading large codebases. This aims
// to reduce confusion by requiring explicit notation of RAII objects
//
// This kind of wrapper class could be useful for other stuff.
// This could be easily extended to force an explicit 'release' call
//
#include <iostream>
#define RAII_CLASS(X) \
private: \
friend class RAII<X>; \
virtual ~X();
template<class T>
class RAII {
private:
char _data[sizeof(T)];
T* data() { return (T*)_data; }
const T* data() const { return (T*)_data; }
// static const uint64_t POISON = 0x4141414141414141;
// bool is_valid() const { return *((uint64_t*)_data) != &_data ^ POISON; }
public:
template<typename... args>
RAII(args... a) {
new (_data) T(a...);
}
// void release() {
// ((T*)_data)->~T();
// *((uint64_t*)_data) = &_data ^ POISON;
// }
~RAII() {
((T*)_data)->~T();
// assert(!is_valid());
}
const T* operator *() const { return data(); }
const T* operator ->() const { return data(); }
T* operator *() { return data(); }
T* operator ->() { return data(); }
operator T&() const { return *data(); }
};
class ScopedResource {
RAII_CLASS(ScopedResource);
private:
int resource = 0;
public:
ScopedResource(int res) : resource(res) {
std::cout << "Acquired resource " << resource << std::endl;
}
int getResource() const { return resource; }
};
ScopedResource::~ScopedResource() {
std::cout << "Released resource " << resource << std::endl;
}
int main() {
auto res = RAII<ScopedResource>(100);
std::cout << "Accessed resource " << res->getResource() << std::endl;
// res.release();
return 0;
}