Skip to content

Commit

Permalink
Implement vector constructor to support single-pass input iterator range
Browse files Browse the repository at this point in the history
  • Loading branch information
winner245 committed Oct 19, 2024
1 parent acc07e0 commit d12eca6
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 3 deletions.
4 changes: 4 additions & 0 deletions MyTinySTL/iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ struct has_iterator_cat_of
template <class T, class U>
struct has_iterator_cat_of<T, U, false> : public m_false_type {};

template <class Iter>
struct is_exactly_input_iterator : public m_bool_constant<has_iterator_cat_of<Iter, input_iterator_tag>::value &&
!has_iterator_cat_of<Iter, forward_iterator_tag>::value> {};

template <class Iter>
struct is_input_iterator : public has_iterator_cat_of<Iter, input_iterator_tag> {};

Expand Down
81 changes: 81 additions & 0 deletions MyTinySTL/stream_iterator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#ifndef MYTINYSTL_STREAM_ITERATOR_H_
#define MYTINYSTL_STREAM_ITERATOR_H_

#include "basic_string.h"

namespace mystl
{

template<typename T, typename CharT = char,
typename Traits = std::char_traits<CharT>, typename Dist = ptrdiff_t>
class istream_iterator
: public iterator<input_iterator_tag, T, Dist, const T*, const T&>
{
public:
using char_type = CharT;
using traits_type = Traits;
using istream_type = std::basic_istream<CharT, Traits>;

istream_iterator() /* noexcept(std::is_nothrow_default_constructible<T>::value) */
: m_stream{nullptr}, m_value{} {}

istream_iterator(istream_type& is)
: m_stream{std::addressof(is)}
{ read(); }

istream_iterator(const istream_iterator& other) /* noexcept(std::is_nothrow_copy_constructible<T>::value) */
= default; // memberwise copy

istream_iterator& operator=(const istream_iterator&) = default; // memberwise copy-asgn

~istream_iterator() = default;

const T& operator*() const noexcept {
MYSTL_DEBUG(m_stream != nullptr);
return m_value;
}

const T* operator->() const noexcept {
return std::addressof(*this);
}

istream_iterator& operator++() {
MYSTL_DEBUG(m_stream != nullptr);
read();
return *this;
}

istream_iterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}

private:
istream_type* m_stream;
T m_value;

void read() {
if (m_stream && !(*m_stream >> m_value)) { // m_stream 有效且读到 EOS
m_stream = nullptr;
}
}

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

friend bool operator!=(const istream_iterator& lhs, const istream_iterator& rhs) {
return lhs.m_stream != rhs.m_stream;
}
};


// TODO
// template<typename T, typename CharT = char,
// typename Traits = char_traits<CharT> >
// class ostream_iterator : public iterator<output_iterator_tag, void, void, void, void> {};
}


#endif
12 changes: 11 additions & 1 deletion MyTinySTL/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,17 @@ class vector
{ fill_init(n, value); }

template <class Iter, typename std::enable_if<
mystl::is_input_iterator<Iter>::value, int>::type = 0>
mystl::is_exactly_input_iterator<Iter>::value, int>::type = 0>
vector(Iter first, Iter last)
{
try_init();
for (; first != last; ++first) {
emplace_back(*first);
}
}

template <class Iter, typename std::enable_if<
mystl::is_forward_iterator<Iter>::value, int>::type = 0>
vector(Iter first, Iter last)
{
MYSTL_DEBUG(!(last < first));
Expand Down
10 changes: 8 additions & 2 deletions Test/vector_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@

// vector test : 测试 vector 的接口与 push_back 的性能

#include <vector>
#include <vector>

#include "../MyTinySTL/vector.h"
#include "test.h"
#include "stream_iterator.h" // 用于测试 input_iterator 迭代器版构造函数

namespace mystl
{
Expand All @@ -32,7 +33,6 @@ void vector_test()
v8 = v3;
v9 = std::move(v3);
v10 = { 1,2,3,4,5,6,7,8,9 };

FUN_AFTER(v1, v1.assign(8, 8));
FUN_AFTER(v1, v1.assign(a, a + 5));
FUN_AFTER(v1, v1.emplace(v1.begin(), 0));
Expand Down Expand Up @@ -90,6 +90,12 @@ void vector_test()
FUN_AFTER(v1, v1.shrink_to_fit());
FUN_VALUE(v1.size());
FUN_VALUE(v1.capacity());

std::istringstream is("1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9");
mystl::istream_iterator<int> beg{is}, end;
mystl::vector<int> v11{beg, end};
COUT(v11);

PASSED;
#if PERFORMANCE_TEST_ON
std::cout << "[--------------------- Performance Testing ---------------------]\n";
Expand Down

0 comments on commit d12eca6

Please sign in to comment.