Intuition
If you want to write code which can generalize across type of the argument/object, you can use a templates.
Explanation
Templates
Regular templates can be used to re-use a particular piece of code or a class for different types
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #include <iostream>
template<typename T>
void print(const T &value)
{
std::cout << value << std::endl;
}
int main()
{
print(42);
print("Answers are needed");
return 0;
}
|
Why is this relevant?
You can use templates to implement a basic shared_ptr like class for basic POD(plain old data) types.
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 | #include <iostream>
namespace toy
{
template <typename T>
class SharedPtr
{
public:
explicit SharedPtr(const T& value) : data(new T(value)), ref_count(new size_t(1))
{
}
SharedPtr(const SharedPtr<T>& other) : data(other.data), ref_count(other.ref_count)
{
// If ref_count > 0 then augment ref_count which means there are already pointers to the underlying data
if (ref_count)
{
(*ref_count)++;
}
}
~SharedPtr()
{
if (ref_count)
{
(*ref_count)--;
// If ref_count reaches zero after this destructor call, delete data and ref_count
if (*ref_count == 0)
{
delete data;
delete ref_count;
}
data = nullptr;
ref_count = nullptr;
}
}
T& operator*() const
{
return *data;
}
T* get() const
{
return data;
}
private:
T* data;
size_t* ref_count;
};
} // namespace toy
int main()
{
toy::SharedPtr<int> test_ptr(10);
std::cout << test_ptr.get() << std::endl;
return 0;
}
|