jeudi 1 septembre 2016

Iterator for a list implemented using unique_ptr

I am creating a datastructure that uses unique_ptr. I now want to define different iterators over this datastructure, however the nodes of my data structure are part of the data itself. Because of this I want the iterators to return the actual nodes and not only the values contained within.

Here is what I got so far (much simplified example):

#include <algorithm>
#include <iostream>
#include <memory>

using namespace std;

template <typename T> struct node {
  node(T val) : val(val), next(nullptr) {}
  node(T val, unique_ptr<node<T>> &n) : val(val), next(move(n)) {}
  T val;
  unique_ptr<node<T>> next;

  template <bool Const = true> struct iter {
    using reference =
        typename std::conditional<Const, const node<T> *, node<T> *>::type;
    iter() : nptr(nullptr) {}
    iter(node<T> *n) : nptr(n) {}

    reference operator*() { return nptr; }

    iter &operator++() {
      nptr = nptr->next.get();
      return *this;
    }

    friend bool operator==(const iter &lhs, const iter &rhs) {
      return lhs.nptr == rhs.nptr;
    }

    friend bool operator!=(const iter &lhs, const iter &rhs) {
      return lhs.nptr != rhs.nptr;
    }
    node<T> *nptr;
  };

  iter<> begin() const { return iter<>(this); }
  iter<> end() const { return iter<>(); }

  iter<false> begin() { return iter<false>(this); }
  iter<false> end() { return iter<false>(); }
};

template <typename T> void pretty_print(const unique_ptr<node<T>> &l) {
  auto it = l->begin();
  while (it != l->end()) {
    auto elem = *it;
    cout << elem->val << endl;
    ++it;
  }
}

int main() {
  auto a = make_unique<node<int>>(4);
  auto b = make_unique<node<int>>(3, a);
  auto c = make_unique<node<int>>(2, b);
  auto d = make_unique<node<int>>(1, c);

  for (auto *elem : *d) {
    elem->val = elem->val - 1;
  }

  pretty_print(d);

  return 0;
}

Is it considered bad practice to expose the raw pointers to the elements of the datastructure in this way? Will this work in a more complex example, especially in regard to const-correctness?

Aucun commentaire:

Enregistrer un commentaire