Initial Course
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
add_course_exercise(NAME auto_and_range_for MODULE 09_cpp11 STANDARD 11
|
||||
SOURCES src/auto_and_range_for.cpp test/auto_and_range_for_test.cpp)
|
||||
add_course_exercise(NAME smart_pointers MODULE 09_cpp11 STANDARD 11
|
||||
SOURCES src/smart_pointers.cpp test/smart_pointers_test.cpp)
|
||||
add_course_exercise(NAME move_semantics MODULE 09_cpp11 STANDARD 11
|
||||
SOURCES src/move_semantics.cpp test/move_semantics_test.cpp)
|
||||
add_course_exercise(NAME constexpr_nullptr MODULE 09_cpp11 STANDARD 11
|
||||
SOURCES src/constexpr_nullptr.cpp test/constexpr_nullptr_test.cpp)
|
||||
@@ -0,0 +1,17 @@
|
||||
# Module 09: C++11 Foundations
|
||||
|
||||
## Learning Goals
|
||||
|
||||
- Use `auto`, range-based for, and uniform initialization
|
||||
- Manage ownership with smart pointers
|
||||
- Understand move semantics and rvalue references
|
||||
- Apply `constexpr`, `nullptr`, and `enum class`
|
||||
|
||||
## Exercises
|
||||
|
||||
| Exercise | Standard Feature |
|
||||
|----------|------------------|
|
||||
| `auto_and_range_for` | Type deduction, range-for |
|
||||
| `smart_pointers` | unique_ptr, shared_ptr |
|
||||
| `move_semantics` | std::move, move constructors |
|
||||
| `constexpr_nullptr` | constexpr functions, nullptr, enum class |
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
[[nodiscard]] auto double_values(const std::vector<int>& input) -> std::vector<int>;
|
||||
[[nodiscard]] auto join_with_auto(const std::vector<std::string>& parts) -> std::string;
|
||||
[[nodiscard]] auto count_if_positive(const std::vector<int>& input) -> int;
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
enum class Color { Red, Green, Blue };
|
||||
|
||||
[[nodiscard]] auto to_index(Color color) -> int;
|
||||
[[nodiscard]] auto square(int value) -> int;
|
||||
[[nodiscard]] auto find_null(int* ptr) -> int*;
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
class MovableBuffer {
|
||||
public:
|
||||
MovableBuffer() = default;
|
||||
explicit MovableBuffer(std::vector<int> data);
|
||||
MovableBuffer(const MovableBuffer&) = delete;
|
||||
MovableBuffer(MovableBuffer&& other) noexcept;
|
||||
auto operator=(MovableBuffer&& other) noexcept -> MovableBuffer&;
|
||||
|
||||
[[nodiscard]] auto size() const -> std::size_t;
|
||||
[[nodiscard]] auto data() const -> const std::vector<int>&;
|
||||
|
||||
private:
|
||||
std::vector<int> data_;
|
||||
};
|
||||
|
||||
[[nodiscard]] auto consume(MovableBuffer buffer) -> std::size_t;
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
[[nodiscard]] auto make_counter(int start) -> std::unique_ptr<int>;
|
||||
[[nodiscard]] auto shared_total(const std::vector<std::shared_ptr<int>>& values) -> int;
|
||||
[[nodiscard]] auto clone_unique(const std::unique_ptr<int>& value) -> std::unique_ptr<int>;
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "auto_and_range_for.hpp"
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
auto double_values(const std::vector<int>& input) -> std::vector<int> {
|
||||
(void)input;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto join_with_auto(const std::vector<std::string>& parts) -> std::string {
|
||||
(void)parts;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto count_if_positive(const std::vector<int>& input) -> int {
|
||||
(void)input;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "constexpr_nullptr.hpp"
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
auto to_index(Color color) -> int {
|
||||
switch (color) {
|
||||
case Color::Red: return 0;
|
||||
case Color::Green: return 1;
|
||||
case Color::Blue: return 2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto square(int value) -> int {
|
||||
(void)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto find_null(int* ptr) -> int* {
|
||||
(void)ptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "move_semantics.hpp"
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
MovableBuffer::MovableBuffer(std::vector<int> data) : data_(std::move(data)) {}
|
||||
|
||||
MovableBuffer::MovableBuffer(MovableBuffer&& other) noexcept : data_(std::move(other.data_)) {}
|
||||
|
||||
auto MovableBuffer::operator=(MovableBuffer&& other) noexcept -> MovableBuffer& {
|
||||
if (this != &other) {
|
||||
data_ = std::move(other.data_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto MovableBuffer::size() const -> std::size_t { return data_.size(); }
|
||||
auto MovableBuffer::data() const -> const std::vector<int>& { return data_; }
|
||||
|
||||
auto consume(MovableBuffer buffer) -> std::size_t {
|
||||
(void)buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "smart_pointers.hpp"
|
||||
|
||||
namespace cpp11 {
|
||||
|
||||
auto make_counter(int start) -> std::unique_ptr<int> {
|
||||
(void)start;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto shared_total(const std::vector<std::shared_ptr<int>>& values) -> int {
|
||||
(void)values;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto clone_unique(const std::unique_ptr<int>& value) -> std::unique_ptr<int> {
|
||||
(void)value;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace cpp11
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "auto_and_range_for.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(AutoAndRangeFor, DoubleValues) {
|
||||
EXPECT_EQ(cpp11::double_values({1, 2, 3}), (std::vector<int>{2, 4, 6}));
|
||||
}
|
||||
|
||||
TEST(AutoAndRangeFor, JoinWithAuto) {
|
||||
EXPECT_EQ(cpp11::join_with_auto({"C", "++", "11"}), "C++11");
|
||||
}
|
||||
|
||||
TEST(AutoAndRangeFor, CountIfPositive) {
|
||||
EXPECT_EQ(cpp11::count_if_positive({-1, 0, 2, 3}), 2);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "constexpr_nullptr.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(ConstexprNullptr, EnumClass) {
|
||||
EXPECT_EQ(cpp11::to_index(cpp11::Color::Green), 1);
|
||||
EXPECT_EQ(cpp11::square(4), 16);
|
||||
}
|
||||
|
||||
TEST(ConstexprNullptr, FindNull) {
|
||||
int x = 1;
|
||||
EXPECT_EQ(cpp11::find_null(&x), &x);
|
||||
EXPECT_EQ(cpp11::find_null(nullptr), nullptr);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "move_semantics.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(MoveSemantics, MoveTransfersOwnership) {
|
||||
cpp11::MovableBuffer source{{1, 2, 3}};
|
||||
const auto moved_size = cpp11::consume(std::move(source));
|
||||
EXPECT_EQ(moved_size, 3U);
|
||||
EXPECT_EQ(source.size(), 0U);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "smart_pointers.hpp"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(SmartPointers, MakeCounter) {
|
||||
auto counter = cpp11::make_counter(42);
|
||||
ASSERT_NE(counter, nullptr);
|
||||
EXPECT_EQ(*counter, 42);
|
||||
}
|
||||
|
||||
TEST(SmartPointers, SharedTotal) {
|
||||
std::vector<std::shared_ptr<int>> values;
|
||||
values.push_back(std::make_shared<int>(1));
|
||||
values.push_back(std::make_shared<int>(2));
|
||||
EXPECT_EQ(cpp11::shared_total(values), 3);
|
||||
}
|
||||
|
||||
TEST(SmartPointers, CloneUnique) {
|
||||
auto original = cpp11::make_counter(7);
|
||||
auto copy = cpp11::clone_unique(original);
|
||||
ASSERT_NE(copy, nullptr);
|
||||
EXPECT_EQ(*copy, 7);
|
||||
}
|
||||
Reference in New Issue
Block a user