Skip to content

Commit 45968ef

Browse files
author
Dave Bartolomeo
committed
C++: Add shared test headers to emulate standard library types
1 parent 5085e46 commit 45968ef

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

cpp/ql/test/include/memory.h

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#if !defined(CODEQL_MEMORY_H)
2+
#define CODEQL_MEMORY_H
3+
4+
namespace std {
5+
namespace detail {
6+
template<typename T>
7+
class compressed_pair_element {
8+
T element;
9+
10+
public:
11+
compressed_pair_element() = default;
12+
compressed_pair_element(const T& t) : element(t) {}
13+
14+
T& get() { return element; }
15+
16+
const T& get() const { return element; }
17+
};
18+
19+
template<typename T, typename U>
20+
struct compressed_pair : private compressed_pair_element<T>, private compressed_pair_element<U> {
21+
compressed_pair() = default;
22+
compressed_pair(T& t) : compressed_pair_element<T>(t), compressed_pair_element<U>() {}
23+
compressed_pair(const compressed_pair&) = delete;
24+
compressed_pair(compressed_pair<T, U>&&) noexcept = default;
25+
26+
T& first() { return static_cast<compressed_pair_element<T>&>(*this).get(); }
27+
U& second() { return static_cast<compressed_pair_element<U>&>(*this).get(); }
28+
29+
const T& first() const { return static_cast<const compressed_pair_element<T>&>(*this).get(); }
30+
const U& second() const { return static_cast<const compressed_pair_element<U>&>(*this).get(); }
31+
};
32+
}
33+
34+
template<class T>
35+
struct default_delete {
36+
void operator()(T* ptr) const { delete ptr; }
37+
};
38+
39+
template<class T>
40+
struct default_delete<T[]> {
41+
template<class U>
42+
void operator()(U* ptr) const { delete[] ptr; }
43+
};
44+
45+
template<class T, class Deleter = default_delete<T> >
46+
class unique_ptr {
47+
private:
48+
detail::compressed_pair<T*, Deleter> data;
49+
public:
50+
constexpr unique_ptr() noexcept {}
51+
explicit unique_ptr(T* ptr) noexcept : data(ptr) {}
52+
unique_ptr(const unique_ptr& ptr) = delete;
53+
unique_ptr(unique_ptr&& ptr) noexcept = default;
54+
55+
unique_ptr& operator=(unique_ptr&& ptr) noexcept = default;
56+
57+
T& operator*() const { return *get(); }
58+
T* operator->() const noexcept { return get(); }
59+
60+
T* get() const noexcept { return data.first(); }
61+
T* release() noexcept {
62+
Deleter& d = data.second();
63+
d(data.first());
64+
data.first() = nullptr;
65+
}
66+
67+
~unique_ptr() {
68+
Deleter& d = data.second();
69+
d(data.first());
70+
}
71+
};
72+
73+
template<typename T, class... Args> unique_ptr<T> make_unique(Args&&... args) {
74+
return unique_ptr<T>(new T(args...)); // std::forward calls elided for simplicity.
75+
}
76+
77+
class ctrl_block {
78+
unsigned uses;
79+
80+
public:
81+
ctrl_block() : uses(1) {}
82+
83+
void inc() { ++uses; }
84+
bool dec() { return --uses == 0; }
85+
86+
virtual void destroy() = 0;
87+
virtual ~ctrl_block() {}
88+
};
89+
90+
template<typename T, class Deleter = default_delete<T> >
91+
struct ctrl_block_impl: public ctrl_block {
92+
T* ptr;
93+
Deleter d;
94+
95+
ctrl_block_impl(T* ptr, Deleter d) : ptr(ptr), d(d) {}
96+
virtual void destroy() override { d(ptr); }
97+
};
98+
99+
template<class T>
100+
class shared_ptr {
101+
private:
102+
ctrl_block* ctrl;
103+
T* ptr;
104+
105+
void dec() {
106+
if(ctrl->dec()) {
107+
ctrl->destroy();
108+
delete ctrl;
109+
}
110+
}
111+
112+
void inc() {
113+
ctrl->inc();
114+
}
115+
116+
public:
117+
constexpr shared_ptr() noexcept = default;
118+
shared_ptr(T* ptr) : ctrl(new ctrl_block_impl<T>(ptr, default_delete<T>())) {}
119+
shared_ptr(const shared_ptr& s) noexcept : ptr(s.ptr), ctrl(s.ctrl) {
120+
inc();
121+
}
122+
shared_ptr(shared_ptr&& s) noexcept = default;
123+
shared_ptr(unique_ptr<T>&& s) : shared_ptr(s.release()) {
124+
}
125+
T* operator->() const { return ptr; }
126+
127+
T& operator*() const { return *ptr; }
128+
129+
~shared_ptr() { dec(); }
130+
};
131+
132+
template<typename T, class... Args> shared_ptr<T> make_shared(Args&&... args) {
133+
return shared_ptr<T>(new T(args...)); // std::forward calls elided for simplicity.
134+
}
135+
}
136+
137+
#endif

cpp/ql/test/include/type_traits.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#if !defined(CODEQL_TYPE_TRAITS_H)
2+
#define CODEQL_TYPE_TRAITS_H
3+
4+
namespace std {
5+
template<typename T>
6+
struct remove_reference {
7+
typedef T type;
8+
};
9+
10+
template<typename T>
11+
struct remove_reference<T&> {
12+
typedef T type;
13+
};
14+
15+
template<typename T>
16+
struct remove_reference<T&&> {
17+
typedef T type;
18+
};
19+
}
20+
21+
#endif

cpp/ql/test/include/utility.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#if !defined(CODEQL_UTILITY_H)
2+
#define CODEQL_UTILITY_H
3+
4+
#include "type_traits.h"
5+
6+
namespace std {
7+
template<typename T>
8+
typename remove_reference<T>::type&& move(T&& src) {
9+
return static_cast<typename remove_reference<T>::type&&>(src);
10+
}
11+
}
12+
13+
#endif

0 commit comments

Comments
 (0)