From c9b6b9a5ca082fe7c1b6f58d7713f785a9eb6a5c Mon Sep 17 00:00:00 2001 From: Martial Simon Date: Mon, 15 Sep 2025 01:08:27 +0200 Subject: add: graphs et rushs --- graphs/cpp/smtptr/main.cc | 20 ++++ graphs/cpp/smtptr/shared_pointer.hh | 166 +++++++++++++++++++++++++++++++ graphs/cpp/smtptr/shared_pointer.hxx | 144 +++++++++++++++++++++++++++ graphs/cpp/smtptr/shared_pointer_is_a.cc | 47 +++++++++ 4 files changed, 377 insertions(+) create mode 100644 graphs/cpp/smtptr/main.cc create mode 100644 graphs/cpp/smtptr/shared_pointer.hh create mode 100644 graphs/cpp/smtptr/shared_pointer.hxx create mode 100644 graphs/cpp/smtptr/shared_pointer_is_a.cc (limited to 'graphs/cpp/smtptr') diff --git a/graphs/cpp/smtptr/main.cc b/graphs/cpp/smtptr/main.cc new file mode 100644 index 0000000..a574d45 --- /dev/null +++ b/graphs/cpp/smtptr/main.cc @@ -0,0 +1,20 @@ +#include "shared_pointer.hh" + +int main() +{ + // Lifetime of the data + { + SharedPointer p2; + { + SharedPointer p1{ new int{ 5 } }; + p2 = p1; // Now both SharedPointers own the memory + } + // p1 is freed, but the int pointer remains + // Memory still exists, due to p2 + std::cout << "Value of p2: " << *p2 << std::endl; // Output: 5 + } + // p2 is freed, and since no one else owns the memory, + // the int pointer is freed too + + return 0; +} diff --git a/graphs/cpp/smtptr/shared_pointer.hh b/graphs/cpp/smtptr/shared_pointer.hh new file mode 100644 index 0000000..cc24243 --- /dev/null +++ b/graphs/cpp/smtptr/shared_pointer.hh @@ -0,0 +1,166 @@ +#pragma once + +#include +#include +#include + +template +class SharedPointer +{ +public: + // The type pointed to. + using element_type = T; + + /** + ** \brief Construct a counted reference to a newly allocated object. + */ + SharedPointer(element_type* p = nullptr); + + /** + ** \brief Destroy the SharedPointer. + ** The object pointed to is destroyed only if it is not referenced anymore. + ** Take care to free everything ... + */ + ~SharedPointer(); + + /** + ** \brief Copy constructor. + ** \return A new SharedPointer, pointing + ** to the underlying data of \a other. + ** + ** Although the implementation is subsumed by the previous, more + ** generic one, the C++ standard still mandates this specific + ** signature. Otherwise, the compiler will provide a default + ** implementation, which is of course wrong. Note that the + ** same applies for the assignment operator. + */ + SharedPointer(const SharedPointer& other); + + /// \name Assignments. + /// \{ + + /** + ** \brief Replace the underlying data with \a p + ** A call to \c reset is strictly equivalent to: + ** \code + ** r = SharedPointer(p); + ** \endcode + ** This line implicitly calls the destructor of \a r before assigning + ** it a new value. + ** \warning You can't reset your \c SharedPointer with the + ** same pointer as the current one. In this case, nothing should + ** be done. + ** \warning Be mindful of other \c SharedPointers + ** which could also be pointing to the same data. + */ + void reset(element_type* p); + + /** + ** \brief Reference assignment + ** Its behavior is similar to \c reset() but you + ** have to use the existing SharedPointer \a other + ** instead of creating a new instance. + */ + SharedPointer& + operator=(const SharedPointer& other); + /// \} + + /// \name Access to data. + /// \{ + + // Access via a reference. + element_type& operator*() const; + // Access via a pointer. + element_type* operator->() const; + + // Returns the underlying data pointer. + element_type* get() const; + + // Returns the number of SharedPointer objects referring to the same managed + // object + long use_count() const; + /// \} + + /// \name Equality operators. + /// \{ + + /** + ** \brief Reference comparison. + ** Returns true if the two references point to the same object. + */ + template + bool operator==(const SharedPointer& rhs) const; + + /** + ** \brief Reference comparison. + ** Returns false if the two references point to the same object. + */ + template + bool operator!=(const SharedPointer& rhs) const; + + /** + ** \brief Reference comparison. + ** Returns true if this points to \a p. + */ + bool operator==(const element_type* p) const; + + /** + ** \brief Reference comparison. + ** Returns false if this points to \a p. + */ + bool operator!=(const element_type* p) const; + + /** + ** \brief Move assignment operator for SharedPointer. + ** + ** This operator transfers ownership of the managed object from the + ** \a other to this SharePointer. + ** After the assignment, the \a other will be empty. + ** \warning Don't forget to update the reference counter. + ** + ** Returns a reference to this SharedPointer. + */ + SharedPointer& operator=(SharedPointer&& other) noexcept; + + /** + ** \brief Move constructor for SharedPointer. + ** + ** This constructor transfers ownership of the managed object from \a other + ** SharedPointer to the newly created SharedPointer. + ** + */ + SharedPointer(SharedPointer&& other); + + /// \} + + /** + ** \brief Test for validity + ** Returns true if the reference is valid, i.e. it points to an object. + ** This conversion operator allows users to write: + ** + ** \code + ** SharedPointer p1; + ** if (p1) // Here false + ** ... + ** \endcode + */ + operator bool() const; + + /** + ** \brief Test fellowship. + ** Returns true if the SharedPointer points to an object which + ** is of the specified type. + ** Look at the given example file shared_pointer_is_a.cc + ** to better understand its purpose. + */ + template + bool is_a() const; + +private: + // Pointer to the underlying data. + element_type* data_; + // A counter shared between all ref pointers to \a data_. + long* count_; +}; + +#include "shared_pointer.hxx" diff --git a/graphs/cpp/smtptr/shared_pointer.hxx b/graphs/cpp/smtptr/shared_pointer.hxx new file mode 100644 index 0000000..fbc0792 --- /dev/null +++ b/graphs/cpp/smtptr/shared_pointer.hxx @@ -0,0 +1,144 @@ +#pragma once +#include "shared_pointer.hh" +template +SharedPointer::SharedPointer(element_type* p) +{ + if (p == nullptr) + { + data_ = nullptr; + count_ = nullptr; + } + else + { + data_ = p; + count_ = new long{ 1 }; + } +} +template +SharedPointer::~SharedPointer() +{ + if (count_ != nullptr) + { + (*count_)--; + if (*count_ == 0) + { + delete count_; + if (data_ != nullptr) + delete data_; + } + } +} +template +SharedPointer::SharedPointer(const SharedPointer& other) +{ + this->~SharedPointer(); + data_ = other.data_; + if (data_ == nullptr) + count_ = nullptr; + count_ = other.count_; + if (count_ != nullptr) + (*count_)++; +} +template +void SharedPointer::reset(element_type* p) +{ + if (data_ == p) + return; + this->~SharedPointer(); + data_ = p; + if (p == nullptr) + count_ = nullptr; + else + count_ = new long{ 1 }; +} +template +SharedPointer& SharedPointer::operator=(const SharedPointer& other) +{ + this->~SharedPointer(); + + data_ = other.data_; + count_ = other.count_; + if (nullptr != other.data_) + { + (*this->count_)++; + } + return *this; +} +template +T& SharedPointer::operator*() const +{ + return *data_; +} + +template +T* SharedPointer::operator->() const +{ + return data_; +} +template +T* SharedPointer::get() const +{ + return data_; +} +template +long SharedPointer::use_count() const +{ + if (count_ == nullptr) + return 0; + return *count_; +} +template +template +bool SharedPointer::operator==(const SharedPointer& rhs) const +{ + if (rhs.data_ == this->data_) + return true; + return false; +} +template +template +bool SharedPointer::operator!=(const SharedPointer& rhs) const +{ + return !(*this == rhs); +} +template +bool SharedPointer::operator==(const T* p) const +{ + return this->data_ == p; +} +template +bool SharedPointer::operator!=(const T* p) const +{ + return this->data_ != p; +} +template +SharedPointer& SharedPointer::operator=(SharedPointer&& other) noexcept +{ + this->~SharedPointer(); + data_ = other.data_; + count_ = other.count_; + other.data_ = nullptr; + other.count_ = nullptr; + return *this; +} +template +SharedPointer::SharedPointer(SharedPointer&& other) +{ + this->~SharedPointer(); + data_ = other.data_; + count_ = other.count_; + + other.data_ = nullptr; + other.count_ = nullptr; +} +template +SharedPointer::operator bool() const +{ + return data_ != nullptr; +} +template +template +bool SharedPointer::is_a() const +{ + return dynamic_cast(data_); +} \ No newline at end of file diff --git a/graphs/cpp/smtptr/shared_pointer_is_a.cc b/graphs/cpp/smtptr/shared_pointer_is_a.cc new file mode 100644 index 0000000..b6dcb95 --- /dev/null +++ b/graphs/cpp/smtptr/shared_pointer_is_a.cc @@ -0,0 +1,47 @@ +#include "shared_pointer.hh" + +class Animal +{ +public: + virtual ~Animal() + {} +}; + +class Cat : public Animal +{ +public: + void meow() + { + std::cout << "Meow!\n"; + } +}; + +class Dog : public Animal +{ +public: + void bark() + { + std::cout << "Woof!\n"; + } +}; + +int main() +{ + SharedPointer animalPtr{ new Cat }; + if (animalPtr.is_a()) + { // true + std::cout << "The pointer points to a Cat.\n"; + } + + SharedPointer animalPtr2{ new Dog }; + if (animalPtr2.is_a()) + { // false + std::cout << "The pointer points to a Cat.\n"; + } + else if (animalPtr2.is_a()) + { + std::cout << "The pointer points to a Dog.\n"; + } + + return 0; +} -- cgit v1.2.3