/*
 * Copyright ©2026 Soham Pardeshi. All rights reserved.
 * Permission is hereby granted to students registered for University of
 * Washington CSE 333 for use solely during Summer Quarter 2026 for
 * purposes of the course. No other use, copying, distribution, or
 * modification is permitted without prior written consent. Copyrights
 * for third-party components of this work must be honored. Instructors
 * interested in reusing these course materials should contact the author.
 */

#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <utility>  // std::move
#include <vector>

using std::string;
using std::unique_ptr;

// unique_ptr enforces single ownership: it cannot be copied, only MOVED.
// Moving transfers the raw pointer and leaves the source as nullptr, so
// there is always exactly one owner and exactly one delete.
unique_ptr<string> Make(const char* text) {
  return unique_ptr<string>(new string(text));  // moved out on return
}

int main(int argc, char** argv) {
  unique_ptr<string> a(new string("Hello"));

  // unique_ptr<string> b = a;   // COMPILE ERROR: copy ctor is deleted
  unique_ptr<string> b = std::move(a);

  std::cout << "*b = " << *b << std::endl;
  std::cout << "a is " << (a == nullptr ? "nullptr" : "still valid")
            << std::endl;

  // Ownership can also move into and out of containers.
  std::vector<unique_ptr<string>> v;
  v.push_back(std::move(b));
  v.push_back(Make("World"));

  for (const auto& p : v) {
    std::cout << *p << " ";
  }
  std::cout << std::endl;

  // No deletes anywhere: the vector's destructor destroys each unique_ptr,
  // and each unique_ptr deletes its string.
  return EXIT_SUCCESS;
}