#pragma once #include #include #include #include "StringValue.h" #include "Char.h" class Char; /* Design decisions: * - Everything related to ref-counting is the responsibility of the StringValue class * - Anything dynamically allocated is owned (and thus once deleted) by the StringValue class * (including itself -- this is possible because of the reference counting mechanism) */ class String { private: StringValue* _str; char* copy_and_concat(const String& str) const; char* copy_and_concat(char c) const; public: String() noexcept; String(const char*); String(const String&) noexcept; String& operator=(String); String(String&&) noexcept; ~String() noexcept; friend void swap(String&, String&) noexcept; String operator+(const String&) const; String& operator+=(const String&); String operator+(char) const; String& operator+=(char); bool operator==(const String&) const; const char& operator[](size_t) const; Char operator[](size_t); size_t size() const noexcept; // does not include null-terminator const char* c_str() const; friend std::istream& operator>>(std::istream&, String&); friend class Char; }; std::ostream& operator<<(std::ostream&, const String&);