diff --git a/test/view.cpp b/test/view.cpp index 0f8cf2ec..72f9bf85 100644 --- a/test/view.cpp +++ b/test/view.cpp @@ -9,10 +9,10 @@ main (int, char**) const std::string s = "this is a test string"; const std::string t = "not the same string"; - tap.expect_eq (s, util::make_view(s), "string/view equality"); - tap.expect_neq (s, util::make_view(t), "string/view inequality"); - tap.expect_eq (s.data (), util::make_view (s), "c-str/view equality"); - tap.expect_eq (s, util::view (&*s.cbegin (), &*s.cend ()), "string/pointer-view equality"); + tap.expect (equal (s, util::make_view(s)), "string/view equality"); + tap.expect (!equal (s, util::make_view(t)), "string/view inequality"); + tap.expect (equal (s.data (), util::make_view (s)), "c-str/view equality"); + tap.expect (equal (s, util::view (&*s.cbegin (), &*s.cend ())), "string/pointer-view equality"); return tap.status (); } diff --git a/view.cpp b/view.cpp index 11d60ed0..2c07bc74 100644 --- a/view.cpp +++ b/view.cpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2016 Danny Robson + * Copyright 2016-2017 Danny Robson */ #include "./view.hpp" @@ -23,7 +23,7 @@ /////////////////////////////////////////////////////////////////////////////// #define EQUALITY(A,B) \ bool \ -util::operator== (A a, B b) \ +util::equal (A a, B b) \ { \ return a.size () == a.size () && \ std::equal (a.cbegin (), \ diff --git a/view.hpp b/view.hpp index 26d1efe4..4742d426 100644 --- a/view.hpp +++ b/view.hpp @@ -28,18 +28,24 @@ #include namespace util { - template + template struct view { public: - using value_type = typename std::iterator_traits>::value_type; + //--------------------------------------------------------------------- + using value_type = typename std::iterator_traits< + remove_restrict_t + >::value_type; + + //--------------------------------------------------------------------- constexpr - view (const T &first, const T &last) noexcept: + view (const IteratorT &first, const IteratorT &last) noexcept: m_begin (first), m_end (last) { ; } + //--------------------------------------------------------------------- constexpr view (const view &rhs) noexcept: m_begin (rhs.m_begin), @@ -47,34 +53,38 @@ namespace util { { ; } + //--------------------------------------------------------------------- // technically we could get away without explicitly defining a move // constructor here, but by nulling rhs we can more easily use this // class as a base for unique owning pointers without exposing // begin/end to them directly. constexpr view (view &&rhs) noexcept: - view (T{}, T{}) + view (IteratorT{}, IteratorT{}) { std::swap (m_begin, rhs.m_begin); std::swap (m_end, rhs.m_end); } - template + //--------------------------------------------------------------------- + template constexpr explicit - view (K &klass): + view (ContainerT &klass): m_begin (std::begin (klass)), m_end (std::end (klass)) { ; } - template + //--------------------------------------------------------------------- + template constexpr explicit - view (const K &klass): + view (const ContainerT &klass): m_begin (std::begin (klass)), m_end (std::end (klass)) { ; } + //--------------------------------------------------------------------- view& operator= (const view &rhs) noexcept { @@ -84,43 +94,51 @@ namespace util { } + //--------------------------------------------------------------------- view& operator= (view &&rhs) noexcept { m_begin = rhs.m_begin; m_end = rhs.m_end; - m_begin = T{}; - m_end = T{}; + rhs.m_begin = IteratorT{}; + rhs.m_end = IteratorT{}; return *this; }; - constexpr T begin (void) noexcept { return m_begin; } - constexpr T end (void) noexcept { return m_end; } + //--------------------------------------------------------------------- + constexpr IteratorT begin (void) noexcept { return m_begin; } + constexpr IteratorT end (void) noexcept { return m_end; } - constexpr const T begin (void) const noexcept { return cbegin (); } - constexpr const T end (void) const noexcept { return cend (); } + //--------------------------------------------------------------------- + constexpr const IteratorT begin (void) const noexcept { return cbegin (); } + constexpr const IteratorT end (void) const noexcept { return cend (); } - constexpr const T cbegin (void) const noexcept { return m_begin; } - constexpr const T cend (void) const noexcept { return m_end; } + //--------------------------------------------------------------------- + constexpr const IteratorT cbegin (void) const noexcept { return m_begin; } + constexpr const IteratorT cend (void) const noexcept { return m_end; } + //--------------------------------------------------------------------- auto data (void) { return begin (); } auto data (void) const { return begin (); } + //--------------------------------------------------------------------- constexpr bool empty (void) const noexcept { return m_begin == m_end; } + //--------------------------------------------------------------------- constexpr auto size (void) const noexcept { return std::distance (m_begin, m_end); } + //--------------------------------------------------------------------- constexpr auto redim (int count) const { @@ -130,94 +148,107 @@ namespace util { return view { m_begin, m_begin + count }; }; + //--------------------------------------------------------------------- constexpr value_type& - operator[] (size_t idx) noexcept + operator[] (size_t idx)& noexcept { auto it = begin (); std::advance (it, idx); return *it; } + //--------------------------------------------------------------------- constexpr const value_type& - operator[] (size_t idx) const noexcept + operator[] (size_t idx) const& noexcept { auto it = begin (); std::advance (it, idx); return *it; } - bool - operator== (const view &rhs) const noexcept - { - return rhs.m_begin == m_begin && - rhs.m_end == m_end; - } private: - T m_begin; - T m_end; + //--------------------------------------------------------------------- + IteratorT m_begin; + IteratorT m_end; }; - template + /////////////////////////////////////////////////////////////////////////// + template auto - make_view (const T (&arr)[N]) + make_view (const ValueT (&arr)[N]) { - return util::view (arr + 0, arr + N); + return util::view (arr + 0, arr + N); } - template + //------------------------------------------------------------------------- + template auto - make_view (T &t) + make_view (ContainerT &t) { return util::view { std::begin (t), std::end (t) }; } - template + //------------------------------------------------------------------------- + template auto - make_view (const T &t) + make_view (const ContainerT &t) { return util::view { std::cbegin (t), std::cend (t) }; } - template - auto - make_view (T&&) = delete; - template + //------------------------------------------------------------------------- + // disable the possibility of creating a view to a temporary. note that + // this only works if an lval version has already been defined otherwise + // universal reference rules will capture both lval and rval here. + template auto - make_cview (const T &t) + make_view (ContainerT&&) = delete; + + + /////////////////////////////////////////////////////////////////////////// + template + auto + make_cview (const ContainerT &t) { return util::view { std::cbegin (t), std::cend (t) }; } - template + + //------------------------------------------------------------------------- + template auto - make_view (T first, T last) + make_view (IteratorT first, IteratorT last) { - return view {first, last}; + return view {first, last}; } - template + //------------------------------------------------------------------------- + template auto - make_cview (T *first, T *last) + make_cview (ValueT *first, ValueT *last) { - return view {first, last}; + return view {first, last}; } - // string conversions + /////////////////////////////////////////////////////////////////////////// inline view make_view (const char *str) { return { str, str + strlen (str) }; } + //------------------------------------------------------------------------- inline view make_view (char *str) { return { str, str + strlen (str) }; } + + //------------------------------------------------------------------------- template view make_view (const std::basic_string &str) @@ -228,6 +259,8 @@ namespace util { }; } + + //------------------------------------------------------------------------- template view make_view (std::basic_string &str) @@ -238,31 +271,56 @@ namespace util { }; } + + //------------------------------------------------------------------------- template view make_view (const std::basic_string&&) = delete; + + //------------------------------------------------------------------------- template view make_view (std::basic_string&&) = delete; - // boolean operationrs - template - bool operator!= (view, view); - bool operator== (const std::string&, view); - bool operator== (const std::string&, view); - bool operator== (const std::string&, view); - bool operator== (const std::string&, view); + /////////////////////////////////////////////////////////////////////////// + template + constexpr bool + operator== (const view &a, const view &b) + { + return std::cbegin (a) == std::cbegin (b) && + std::cend (a) == std::cend (b); + } - bool operator== (view, const std::string&); - bool operator== (view, const std::string&); - bool operator== (view, const std::string&); - bool operator== (view, const std::string&); - template + //------------------------------------------------------------------------- + template + constexpr bool + operator!= (const view &a, const view &b) + { + return !(a == b); + } + + + //------------------------------------------------------------------------- + // equality operations for string-like views against std::strings + bool equal (const std::string&, view); + bool equal (const std::string&, view); + bool equal (const std::string&, view); + bool equal (const std::string&, view); + + + bool equal (view, const std::string&); + bool equal (view, const std::string&); + bool equal (view, const std::string&); + bool equal (view, const std::string&); + + + /////////////////////////////////////////////////////////////////////////// + template std::ostream& - operator<< (std::ostream&, view); + operator<< (std::ostream&, view); } #endif