Problem p02265 (C++) — buggy submission, verdict: Runtime Error

#include <cstdio>
#include <memory>

using namespace std;

// #define DEBUG true

#ifdef DEBUG
#define D(s)                                                                   \\
  if (DEBUG) {                                                                 \\
    [&] { s }();                                                               \\
  }
#else
#define D(s)
#endif

template <typename T> class DoublyLinkedList {
  template <typename U> struct Node;
  using ValueType = T;
  using NodeType = Node<ValueType>;
  using PointerType = shared_ptr<NodeType>;

  template <typename U> struct Node {
    PointerType prev;
    PointerType next;
    ValueType value;
    Node(const ValueType &v) : value{v} {}
    ~Node() { D(printf("Destruct %d\\n", value);) }
  };
  PointerType first_;
  PointerType last_;

public:
  void insert(const ValueType &v) {
    auto n = make_shared<NodeType>(v);
    if (first_ != nullptr) {
      D(printf("insert %d before %d\\n", n->value, last_->value);)
      n->next = first_;
      first_->prev = n;
      first_ = n;
    } else {
      first_ = n;
      last_ = n;
    }
  }

  void remove(const ValueType &v) {
    auto p = first_;
    while (p != nullptr) {
      if (p->value == v) {
        if (p == last_) {
          removeLast();
        } else if (p == first_) {
          removeFirst();
        } else {
          p->prev->next = p->next;
          p->next->prev = p->prev;
        }
        return;
      }
      p = p->next;
    }
  }

  void removeFirst() {
    if (last_ == first_) {
      last_ = nullptr;
      first_ = nullptr;
    } else {
      auto newFirst = first_->next;
      newFirst->prev = nullptr;
      first_ = newFirst;
    }
  }

  void removeLast() {
    if (last_ == first_) {
      last_ = nullptr;
      first_ = nullptr;
    } else {

      auto newLast = last_->prev;
      newLast->next = nullptr;
      last_ = newLast;
    }
  }

  template <typename F> void map(F f) const {
    auto p = first_;
    while (p != nullptr) {
      f(p->value);
      p = p->next;
    }
  }

  template <typename F> void map_inverse(F f) const {
    auto p = last_;
    while (p != nullptr) {
      f(p->value);
      p = p->prev;
    }
  }

  void print() const {

    auto p = first_;
    while (p != nullptr) {
      printf("%d", p->value);
      p = p->next;
      if (p != nullptr) {
        putchar(' ');
      }
    }
    putchar('\\n');
  }
};

int main() {
  DoublyLinkedList<int> v;
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    D(v.print();)
    char op[30];
    int num;
    scanf("%s %d", op, &num);
    if (op[0] == 'i') {
      v.insert(num);
    } else if (op[6] == 'F') {
      v.removeFirst();
    } else if (op[6] == 'L') {
      v.removeLast();
    } else {
      v.remove(num);
    }
  }
  v.print();
}

Error: 0

Fixed submission:

#include <cstdio>
#include <memory>

using namespace std;

// #define DEBUG true

#ifdef DEBUG
#define D(s)                                                                   \\
  if (DEBUG) {                                                                 \\
    [&] { s }();                                                               \\
  }
#else
#define D(s)
#endif

template <typename T> class DoublyLinkedList {
  template <typename U> struct Node;
  using ValueType = T;
  using NodeType = Node<ValueType>;
  using PointerType = shared_ptr<NodeType>;

  template <typename U> struct Node {
    PointerType prev;
    PointerType next;
    ValueType value;
    Node(const ValueType &v) : value{v} {}
    ~Node() { D(printf("Destruct %d\\n", value);) }
  };
  PointerType first_;
  PointerType last_;

public:
  void insert(const ValueType &v) {
    auto n = make_shared<NodeType>(v);
    if (first_ != nullptr) {
      D(printf("insert %d before %d\\n", n->value, last_->value);)
      n->next = first_;
      first_->prev = n;
      first_ = n;
    } else {
      first_ = n;
      last_ = n;
    }
  }

  void remove(const ValueType &v) {
    auto p = first_;
    while (p != nullptr) {
      if (p->value == v) {
        if (p == last_) {
          removeLast();
        } else if (p == first_) {
          removeFirst();
        } else {
          p->prev->next = p->next;
          p->next->prev = p->prev;
        }
        return;
      }
      p = p->next;
    }
  }

  void removeFirst() {
    // Error check is omitted
    auto newFirst = first_->next;
    newFirst->prev = nullptr;
    first_ = newFirst;
  }

  void removeLast() {
    auto newLast = last_->prev;
    newLast->next = nullptr;
    last_ = newLast;
  }

  template <typename F> void map(F f) const {
    auto p = first_;
    while (p != nullptr) {
      f(p->value);
      p = p->next;
    }
  }

  template <typename F> void map_inverse(F f) const {
    auto p = last_;
    while (p != nullptr) {
      f(p->value);
      p = p->prev;
    }
  }

  void print() const {

    auto p = first_;
    while (p != nullptr) {
      printf("%d", p->value);
      p = p->next;
      if (p != nullptr) {
        putchar(' ');
      }
    }
    putchar('\\n');
  }
};

int main() {
  DoublyLinkedList<int> v;
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    D(v.print();)
    char op[30];
    int num;
    scanf("%s %d", op, &num);
    if (op[0] == 'i') {
      v.insert(num);
    } else if (op[6] == 'F') {
      v.removeFirst();
    } else if (op[6] == 'L') {
      v.removeLast();
    } else {
      v.remove(num);
    }
  }
  v.print();
}