Skip to content

Commit 402a37d

Browse files
authored
Week 11 (#13)
* Add task 09.09 * Add task 09.05 unique pointer * Add task 09.06 shared pointer * Add task 09.11 two-linked list * Fix shared_ptr cycle in List * task 09.02: logger implementation * task 09.14: odd iterator
1 parent 872dd24 commit 402a37d

28 files changed

+999
-1
lines changed

.clang-tidy

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Checks: '
55
misc-const-correctness,
66
-readability-identifier-length,
77
-readability-else-after-return,
8+
-readability-qualified-auto,
89
-readability-math-missing-parentheses
910
'
1011
CheckOptions:

CMakeLists.txt

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,13 @@ function(cpp_test SOURCE_NAME)
5656
add_dependencies(all-tests ${TARGET_NAME}-run)
5757
endfunction(cpp_test)
5858

59+
60+
##### shared library #####
61+
include_directories(shared)
62+
63+
5964
##### subdirectories #####
60-
set(DIRS week-W week-2 week-3 week-4 week-5 week-6 week-7 week-8 week-9 week-10)
65+
set(DIRS week-W week-2 week-3 week-4 week-5 week-6 week-7 week-8 week-9 week-10 week-11)
6166
foreach(DIR ${DIRS})
6267
add_subdirectory(${DIR})
6368
endforeach()

shared/noncopyable.hpp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
3+
namespace share::util {
4+
5+
class NonCopyable {
6+
protected:
7+
NonCopyable() = default;
8+
9+
public:
10+
NonCopyable(const NonCopyable& other) = delete;
11+
NonCopyable& operator=(const NonCopyable& other) = delete;
12+
};
13+
14+
} // namespace share::util

week-11/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set(DIRS task-09-09 task-09-05 task-09-06 task-09-11 task-09-02 task-09-14)
2+
foreach(DIR ${DIRS})
3+
add_subdirectory(${DIR})
4+
endforeach()

week-11/task-09-02/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include_directories(include)
2+
3+
add_subdirectory(test)

week-11/task-09-02/include/logger.hpp

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#pragma once
2+
3+
#include <cassert>
4+
#include <iostream>
5+
#include <source_location>
6+
7+
#include "noncopyable.hpp"
8+
9+
namespace logger {
10+
11+
class Logger : share::util::NonCopyable {
12+
public:
13+
explicit Logger(const std::source_location location = std::source_location::current())
14+
: loc_(location) {
15+
for (int i = 0; i < nesting; ++i) {
16+
std::cout << " ";
17+
}
18+
std::cout << "\033[1;34m[Logger]\033[0m Begin function " << loc_.function_name()
19+
<< std::endl;
20+
++nesting;
21+
}
22+
23+
~Logger() {
24+
--nesting;
25+
assert(nesting >= 0);
26+
for (int i = 0; i < nesting; ++i) {
27+
std::cout << " ";
28+
}
29+
std::cout << "\033[1;33m[Logger]\033[0m End of function " << loc_.function_name()
30+
<< std::endl;
31+
}
32+
33+
private:
34+
std::source_location loc_;
35+
36+
static int nesting;
37+
};
38+
39+
int Logger::nesting = 0;
40+
41+
} // namespace logger
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cpp_test(test-09-02.cpp)
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <source_location>
4+
5+
#include "logger.hpp"
6+
7+
using logger::Logger;
8+
9+
void foo() { const Logger logger{}; }
10+
11+
void bar() {
12+
const Logger logger{};
13+
foo();
14+
}
15+
16+
TEST(Logger, logs) {
17+
const Logger log{};
18+
bar();
19+
}

week-11/task-09-05/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include_directories(include)
2+
3+
add_subdirectory(test)

week-11/task-09-05/include/unique.hpp

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
#include "noncopyable.hpp"
3+
#include "utility"
4+
5+
namespace memory {
6+
7+
template <typename T>
8+
class Unique : private share::util::NonCopyable {
9+
public:
10+
explicit Unique(T* ptr = nullptr) : data_(ptr) {}
11+
template <typename U>
12+
requires std::convertible_to<U*, T*>
13+
explicit Unique(Unique<U>&& other) : Unique() {
14+
data_ = other.release();
15+
}
16+
Unique(Unique&& other) : Unique() { swap(other); }
17+
18+
template <typename U>
19+
requires std::convertible_to<U*, T*>
20+
auto& operator=(Unique<U>&& other) {
21+
reset(other.release());
22+
return *this;
23+
}
24+
auto& operator=(Unique&& other) noexcept {
25+
reset(other.release());
26+
return *this;
27+
}
28+
29+
~Unique() { reset(); }
30+
31+
void swap(Unique& other) { std::swap(data_, other.data_); }
32+
T* get() const { return data_; }
33+
T* release() { return std::exchange(data_, nullptr); }
34+
void reset(T* ptr = nullptr) {
35+
delete data_;
36+
data_ = ptr;
37+
}
38+
39+
T& operator*() const { return *get(); }
40+
T* operator->() const { return get(); }
41+
explicit operator bool() const { return get() != nullptr; }
42+
43+
private:
44+
T* data_ = nullptr;
45+
};
46+
47+
template <typename T, typename... Ts>
48+
auto make_unique(Ts&&... xs) {
49+
return Unique<T>(new T(std::forward<Ts>(xs)...));
50+
}
51+
52+
} // namespace memory
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cpp_test(test-09-05.cpp)
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#include <gtest/gtest.h>
2+
3+
#include "unique.hpp"
4+
5+
using memory::Unique;
6+
7+
class Base {
8+
public:
9+
explicit Base(int a) : a_(a) {}
10+
virtual ~Base() {}
11+
12+
int a_;
13+
};
14+
15+
class Derived : public Base {
16+
public:
17+
Derived(int a, int b) : Base(a), b_(b) {}
18+
19+
int b_;
20+
};
21+
22+
TEST(UniquePtr, DefaultConstructor) {
23+
const Unique<int> ptr;
24+
EXPECT_EQ(ptr.get(), nullptr);
25+
}
26+
27+
TEST(UniquePtr, ConstructorWithValue) {
28+
const Unique<int> ptr(new int(42));
29+
EXPECT_EQ(*ptr, 42);
30+
}
31+
32+
TEST(UniquePtr, ConstructorWithValueInheritance) {
33+
const Unique<Base> ptr(new Derived(41, 42));
34+
EXPECT_EQ(ptr->a_, 41);
35+
EXPECT_EQ(dynamic_cast<Derived*>(ptr.get())->b_, 42);
36+
}
37+
38+
TEST(UniquePtr, MoveConstructor) {
39+
Unique<int> ptr1(new int(42)); // NOLINT
40+
const Unique<int> ptr2(std::move(ptr1));
41+
EXPECT_EQ(*ptr2, 42);
42+
EXPECT_EQ(ptr1.release(), nullptr); // NOLINT
43+
}
44+
45+
TEST(UniquePtr, MoveConstructorInheritance) {
46+
Unique<Derived> ptr_derived(new Derived(41, 42)); // NOLINT
47+
const Unique<Base> ptr_base(std::move(ptr_derived));
48+
EXPECT_EQ(ptr_base->a_, 41);
49+
EXPECT_EQ(dynamic_cast<Derived*>(ptr_base.get())->b_, 42);
50+
EXPECT_EQ(ptr_derived.release(), nullptr); // NOLINT
51+
}
52+
53+
TEST(UniquePtr, MoveAssignment) {
54+
Unique<int> ptr1(new int(42)); // NOLINT
55+
Unique<int> ptr2;
56+
ptr2 = std::move(ptr1);
57+
EXPECT_EQ(*ptr2, 42);
58+
EXPECT_EQ(ptr1.release(), nullptr); // NOLINT
59+
}
60+
61+
TEST(UniquePtr, MoveAssignmentInheritance) {
62+
Unique<Derived> ptr_derived(new Derived(41, 42)); // NOLINT
63+
Unique<Base> ptr_base;
64+
ptr_base = std::move(ptr_derived);
65+
EXPECT_EQ(ptr_base->a_, 41);
66+
EXPECT_EQ(dynamic_cast<Derived*>(ptr_base.get())->b_, 42);
67+
EXPECT_EQ(ptr_derived.release(), nullptr); // NOLINT
68+
}
69+
70+
TEST(UniquePtr, Reset) {
71+
Unique<int> ptr(new int(42)); // NOLINT
72+
ptr.reset(new int(99)); // NOLINT
73+
EXPECT_EQ(*ptr, 99);
74+
ptr.reset();
75+
EXPECT_EQ(ptr.get(), nullptr);
76+
}
77+
78+
TEST(UniquePtr, Release) {
79+
Unique<int> ptr(new int(42)); // NOLINT
80+
int* raw = ptr.release();
81+
EXPECT_EQ(*raw, 42);
82+
EXPECT_EQ(ptr.get(), nullptr);
83+
delete raw;
84+
}
85+
86+
TEST(UniquePtr, Swap) {
87+
Unique<int> ptr1(new int(42)); // NOLINT
88+
Unique<int> ptr2(new int(99)); // NOLINT
89+
ptr1.swap(ptr2);
90+
EXPECT_EQ(*ptr1, 99);
91+
EXPECT_EQ(*ptr2, 42);
92+
}
93+
94+
TEST(UniquePtr, BooleanConversion) {
95+
const Unique<int> ptr1(new int(42)); // NOLINT
96+
const Unique<int> ptr2;
97+
EXPECT_TRUE(ptr1);
98+
EXPECT_FALSE(ptr2);
99+
}
100+
101+
TEST(UniquePtr, ArrowOperator) {
102+
const Unique<Derived> ptr(new Derived(41, 42)); // NOLINT
103+
EXPECT_EQ(ptr->a_, 41);
104+
EXPECT_EQ(ptr->b_, 42);
105+
}

week-11/task-09-06/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include_directories(include)
2+
3+
add_subdirectory(test)

0 commit comments

Comments
 (0)