diff --git a/src/swcio.cpp b/src/swcio.cpp
index 32724fe8f38685a593c6d82cdbf27448c26a325a..28e189a6f5a19df31c9ee961ffe0fe79be1a7676 100644
--- a/src/swcio.cpp
+++ b/src/swcio.cpp
@@ -174,9 +174,8 @@ cell_record swc_parser::parse_record(std::istringstream &is)
 }
 
 
-std::vector<cell_record> swc_read_cells(std::istream &is)
+cell_record_range_clean::cell_record_range_clean(std::istream &is)
 {
-    std::vector<cell_record> cells;
     std::unordered_set<cell_record::id_type> ids;
 
     std::size_t          num_trees = 0;
@@ -184,40 +183,38 @@ std::vector<cell_record> swc_read_cells(std::istream &is)
     bool                 needsort  = false;
 
     cell_record curr_cell;
-    while ( !(is >> curr_cell).eof()) {
-        if (curr_cell.parent() == -1 && ++num_trees > 1) {
+    for (auto c : swc_get_records<swc_io_raw>(is)) {
+        if (c.parent() == -1 && ++num_trees > 1) {
             // only a single tree is allowed
             break;
         }
 
-        auto inserted = ids.insert(curr_cell.id());
+        auto inserted = ids.insert(c.id());
         if (inserted.second) {
             // not a duplicate; insert cell
-            cells.push_back(curr_cell);
-            if (!needsort && curr_cell.id() < last_id) {
+            cells_.push_back(c);
+            if (!needsort && c.id() < last_id) {
                 needsort = true;
             }
 
-            last_id = curr_cell.id();
+            last_id = c.id();
         }
     }
 
     if (needsort) {
-        std::sort(cells.begin(), cells.end());
+        std::sort(cells_.begin(), cells_.end());
     }
 
     // Renumber cells if necessary
     std::map<cell_record::id_type, cell_record::id_type> idmap;
     cell_record::id_type next_id = 0;
-    for (auto &c : cells) {
+    for (auto &c : cells_) {
         if (c.id() != next_id) {
             c.renumber(next_id, idmap);
         }
 
         ++next_id;
     }
-
-    return std::move(cells);
 }
 
 }   // end of nestmc::io
diff --git a/src/swcio.hpp b/src/swcio.hpp
index 5365c8a5b508f6102e06c08d780cd94a64aeae0b..e267c184b4e462b2015fb8c38866e2133d60b8b1 100644
--- a/src/swcio.hpp
+++ b/src/swcio.hpp
@@ -221,16 +221,6 @@ private:
 
 std::istream &operator>>(std::istream &is, cell_record &cell);
 
-//
-// Reads cells from an input stream until an eof is encountered and returns a
-// cleaned sequence of cell records.
-//
-// For more information check here:
-//   https://github.com/eth-cscs/cell_algorithms/wiki/SWC-file-parsing
-//
-std::vector<cell_record> swc_read_cells(std::istream &is);
-
-
 class cell_record_stream_iterator :
         public std::iterator<std::forward_iterator_tag, cell_record>
 {
@@ -355,8 +345,42 @@ private:
     std::istream &is_;
 };
 
+//
+// Reads cells from an input stream until an eof is encountered and returns a
+// cleaned sequence of cell records.
+//
+// For more information check here:
+//   https://github.com/eth-cscs/cell_algorithms/wiki/SWC-file-parsing
+//
+
 class cell_record_range_clean
 {
+public:
+    using value_type     = cell_record;
+    using reference      = value_type &;
+    using const_referene = const value_type &;
+    using iterator       = std::vector<cell_record>::iterator;
+    using const_iterator = std::vector<cell_record>::const_iterator;
+
+    cell_record_range_clean(std::istream &is);
+
+    iterator begin()
+    {
+        return cells_.begin();
+    }
+
+    iterator end()
+    {
+        return cells_.end();
+    }
+
+    std::size_t size()
+    {
+        return cells_.size();
+    }
+
+private:
+    std::vector<cell_record> cells_;
 };
 
 struct swc_io_raw
@@ -366,11 +390,11 @@ struct swc_io_raw
 
 struct swc_io_clean
 {
-    using cell_range_type = cell_record_range_raw;
+    using cell_range_type = cell_record_range_clean;
 };
 
 template<typename T = swc_io_clean>
- typename T::cell_range_type get_cell_records(std::istream &is)
+ typename T::cell_range_type swc_get_records(std::istream &is)
 {
     return typename T::cell_range_type(is);
 }
diff --git a/tests/test_swcio.cpp b/tests/test_swcio.cpp
index c7b282af14e26a4001216ed3cdf322c0a6bd5d09..7ecd5fc013d98e66428d7a85cb658360e4ca6f2d 100644
--- a/tests/test_swcio.cpp
+++ b/tests/test_swcio.cpp
@@ -186,16 +186,12 @@ TEST(swc_parser, valid_input)
             swc_input << c << "\n";
 
         swc_input << "# this is a final comment\n";
-        try {
-            std::size_t nr_records = 0;
-            cell_record cell;
-            while ( !(swc_input >> cell).eof()) {
-                ASSERT_LT(nr_records, cells_orig.size());
-                expect_cell_equals(cells_orig[nr_records], cell);
-                ++nr_records;
-            }
-        } catch (std::exception &e) {
-            ADD_FAILURE() << "unexpected exception thrown\n";
+
+        std::size_t nr_records = 0;
+        for (auto cell : swc_get_records<swc_io_raw>(swc_input)) {
+            ASSERT_LT(nr_records, cells_orig.size());
+            expect_cell_equals(cells_orig[nr_records], cell);
+            ++nr_records;
         }
     }
 }
@@ -213,8 +209,7 @@ TEST(swc_parser, from_allen_db)
 
     // load the cell records into a std::vector
     std::vector<io::cell_record> nodes;
-    io::cell_record node;
-    while( !(fid >> node).eof()) {
+    for (auto node : io::swc_get_records<io::swc_io_raw>(fid)) {
         nodes.push_back(std::move(node));
     }
 
@@ -234,8 +229,7 @@ TEST(swc_parser, input_cleaning)
         is << "2 1 14.566132 34.873772 7.857000 0.717830 1\n";
         is << "2 1 14.566132 34.873772 7.857000 0.717830 1\n";
 
-        auto cells = swc_read_cells(is);
-        EXPECT_EQ(2u, cells.size());
+        EXPECT_EQ(2u, swc_get_records(is).size());
     }
 
     {
@@ -246,7 +240,7 @@ TEST(swc_parser, input_cleaning)
         is << "3 1 14.566132 34.873772 7.857000 0.717830 -1\n";
         is << "4 1 14.566132 34.873772 7.857000 0.717830 1\n";
 
-        auto cells = swc_read_cells(is);
+        auto cells = swc_get_records(is);
         EXPECT_EQ(2u, cells.size());
     }
 
@@ -259,14 +253,15 @@ TEST(swc_parser, input_cleaning)
         is << "1 1 14.566132 34.873772 7.857000 0.717830 -1\n";
 
         std::array<cell_record::id_type, 4> expected_id_list = {{ 0, 1, 2, 3 }};
-        auto cells = swc_read_cells(is);
-        ASSERT_EQ(4u, cells.size());
 
         auto expected_id = expected_id_list.cbegin();
-        for (const auto &c : cells) {
+        for (auto c : swc_get_records(is)) {
             EXPECT_EQ(*expected_id, c.id());
             ++expected_id;
         }
+
+        // Check that we have read through the whole input
+        EXPECT_EQ(expected_id_list.end(), expected_id);
     }
 
     {
@@ -279,21 +274,23 @@ TEST(swc_parser, input_cleaning)
         is << "51 1 14.566132 34.873772 7.857000 0.717830 1\n";
         is << "61 1 14.566132 34.873772 7.857000 0.717830 51\n";
 
-        auto cells = swc_read_cells(is);
         std::array<cell_record::id_type, 6> expected_id_list =
             {{ 0, 1, 2, 3, 4, 5 }};
         std::array<cell_record::id_type, 6> expected_parent_list =
             {{ -1, 0, 1, 1, 0, 4 }};
-        ASSERT_EQ(6u, cells.size());
 
         auto expected_id = expected_id_list.cbegin();
         auto expected_parent = expected_parent_list.cbegin();
-        for (const auto &c : cells) {
+        for (auto c : swc_get_records(is)) {
             EXPECT_EQ(*expected_id, c.id());
             EXPECT_EQ(*expected_parent, c.parent());
             ++expected_id;
             ++expected_parent;
         }
+
+        // Check that we have read through the whole input
+        EXPECT_EQ(expected_id_list.end(), expected_id);
+        EXPECT_EQ(expected_parent_list.end(), expected_parent);
     }
 }
 
@@ -310,7 +307,7 @@ TEST(cell_record_ranges, raw)
         is << "4 1 14.566132 34.873772 7.857000 0.717830 1\n";
 
         std::vector<cell_record> cells;
-        for (auto c : get_cell_records<swc_io_raw>(is)) {
+        for (auto c : swc_get_records<swc_io_raw>(is)) {
             cells.push_back(c);
         }
 
@@ -318,8 +315,8 @@ TEST(cell_record_ranges, raw)
 
         bool entered = false;
         auto citer = cells.begin();
-        for (auto c : get_cell_records<swc_io_raw>(is)) {
-            EXPECT_TRUE(c.strict_equals(*citer++));
+        for (auto c : swc_get_records<swc_io_raw>(is)) {
+            expect_cell_equals(c, *citer++);
             entered = true;
         }
 
@@ -331,7 +328,7 @@ TEST(cell_record_ranges, raw)
         std::stringstream is;
         is << "1 1 14.566132 34.873772 7.857000 0.717830 -1\n";
 
-        auto ibegin = get_cell_records<swc_io_raw>(is).begin();
+        auto ibegin = swc_get_records<swc_io_raw>(is).begin();
 
         EXPECT_NO_THROW(++ibegin);
         EXPECT_THROW(*ibegin, std::out_of_range);
@@ -343,8 +340,8 @@ TEST(cell_record_ranges, raw)
         std::stringstream is;
         is << "1 1 14.566132 34.873772 7.857000 0.717830 -1\n";
 
-        auto iter = get_cell_records<swc_io_raw>(is).begin();
-        auto iend = get_cell_records<swc_io_raw>(is).end();
+        auto iter = swc_get_records<swc_io_raw>(is).begin();
+        auto iend = swc_get_records<swc_io_raw>(is).end();
 
         cell_record c;
         EXPECT_NO_THROW(c = *iter++);
@@ -365,11 +362,11 @@ TEST(cell_record_ranges, raw)
 
         std::vector<cell_record> cells;
         try {
-            for (auto c : get_cell_records<swc_io_raw>(is)) {
+            for (auto c : swc_get_records<swc_io_raw>(is)) {
                 cells.push_back(c);
             }
 
-            FAIL() << "expected an exception";
+            ADD_FAILURE() << "expected an exception\n";
         } catch (const swc_parse_error &e) {
             EXPECT_EQ(3u, e.lineno());
         }