From d12eca638c8741ad2f00d5a1492b0d8999b6bc42 Mon Sep 17 00:00:00 2001 From: winner245 Date: Sat, 19 Oct 2024 18:46:25 -0400 Subject: [PATCH] Implement vector constructor to support single-pass input iterator range --- MyTinySTL/iterator.h | 4 ++ MyTinySTL/stream_iterator.h | 81 +++++++++++++++++++++++++++++++++++++ MyTinySTL/vector.h | 12 +++++- Test/vector_test.h | 10 ++++- 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 MyTinySTL/stream_iterator.h diff --git a/MyTinySTL/iterator.h b/MyTinySTL/iterator.h index 28a9a69..a3e5cfa 100644 --- a/MyTinySTL/iterator.h +++ b/MyTinySTL/iterator.h @@ -103,6 +103,10 @@ struct has_iterator_cat_of template struct has_iterator_cat_of : public m_false_type {}; +template +struct is_exactly_input_iterator : public m_bool_constant::value && + !has_iterator_cat_of::value> {}; + template struct is_input_iterator : public has_iterator_cat_of {}; diff --git a/MyTinySTL/stream_iterator.h b/MyTinySTL/stream_iterator.h new file mode 100644 index 0000000..3762f03 --- /dev/null +++ b/MyTinySTL/stream_iterator.h @@ -0,0 +1,81 @@ +#ifndef MYTINYSTL_STREAM_ITERATOR_H_ +#define MYTINYSTL_STREAM_ITERATOR_H_ + +#include "basic_string.h" + +namespace mystl +{ + +template, typename Dist = ptrdiff_t> +class istream_iterator +: public iterator +{ +public: + using char_type = CharT; + using traits_type = Traits; + using istream_type = std::basic_istream; + + istream_iterator() /* noexcept(std::is_nothrow_default_constructible::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::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 > +// class ostream_iterator : public iterator {}; +} + + +#endif \ No newline at end of file diff --git a/MyTinySTL/vector.h b/MyTinySTL/vector.h index 5192761..c906930 100644 --- a/MyTinySTL/vector.h +++ b/MyTinySTL/vector.h @@ -80,7 +80,17 @@ class vector { fill_init(n, value); } template ::value, int>::type = 0> + mystl::is_exactly_input_iterator::value, int>::type = 0> + vector(Iter first, Iter last) + { + try_init(); + for (; first != last; ++first) { + emplace_back(*first); + } + } + + template ::value, int>::type = 0> vector(Iter first, Iter last) { MYSTL_DEBUG(!(last < first)); diff --git a/Test/vector_test.h b/Test/vector_test.h index 8b79ef6..b5ddb57 100644 --- a/Test/vector_test.h +++ b/Test/vector_test.h @@ -3,10 +3,11 @@ // vector test : 测试 vector 的接口与 push_back 的性能 -#include +#include #include "../MyTinySTL/vector.h" #include "test.h" +#include "stream_iterator.h" // 用于测试 input_iterator 迭代器版构造函数 namespace mystl { @@ -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)); @@ -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 beg{is}, end; + mystl::vector v11{beg, end}; + COUT(v11); + PASSED; #if PERFORMANCE_TEST_ON std::cout << "[--------------------- Performance Testing ---------------------]\n";