From b88cfcf545bf9c456a7d837d7193e419a2f41cc0 Mon Sep 17 00:00:00 2001 From: Tristan Brindle Date: Wed, 13 May 2020 17:28:09 +0100 Subject: [PATCH 1/2] Fix empty_view empty_view was accidentally privately rather than publicly inhertiting from view_interface. This has been wrong for basically the entire time that NanoRange has ever existed, and nobody (including me) has noticed until now. Hmmm. While we've got the hood up, let's also remove the begin() and end() friends since they're no longer needed, and change size() to return a size_t since everybody loves unsigned types apparently. --- include/nanorange/views/empty.hpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/include/nanorange/views/empty.hpp b/include/nanorange/views/empty.hpp index 2d41792..a58349c 100644 --- a/include/nanorange/views/empty.hpp +++ b/include/nanorange/views/empty.hpp @@ -14,19 +14,15 @@ NANO_BEGIN_NAMESPACE namespace empty_view_ { template -class empty_view : view_interface> { - static_assert(std::is_object::value, ""); +class empty_view : public view_interface> { + static_assert(std::is_object::value); public: static constexpr T* begin() noexcept { return nullptr; } static constexpr T* end() noexcept { return nullptr; } - static constexpr std::ptrdiff_t size() noexcept { return 0; } + static constexpr std::size_t size() noexcept { return 0; } static constexpr T* data() noexcept { return nullptr; } - static constexpr bool empty() noexcept { return true; } - - friend constexpr T* begin(empty_view) noexcept { return nullptr; } - friend constexpr T* end(empty_view) noexcept { return nullptr; } }; } From 31bd0f34d7b7777f7d174bb6a6aad9ee046eef72 Mon Sep 17 00:00:00 2001 From: Tristan Brindle Date: Wed, 13 May 2020 17:32:43 +0100 Subject: [PATCH 2/2] Update view concept definition to match C++20 spec If you're going to write a blog post about something, you should probably make sure your own library implements it correctly, right? This commit removes the heuristic that assumes something is a view if begin() and cbegin() return the same type, which is rather wonderful and means we no longer have to do the ugly special-casing of lots of standard library types (other than string_view, which I can live with). --- include/nanorange/detail/ranges/concepts.hpp | 62 ++------------------ include/nanorange/views/split.hpp | 2 +- test/concepts/ranges.cpp | 16 ++--- test/utility/concepts.cpp | 2 +- 4 files changed, 14 insertions(+), 68 deletions(-) diff --git a/include/nanorange/detail/ranges/concepts.hpp b/include/nanorange/detail/ranges/concepts.hpp index a188533..62068c1 100644 --- a/include/nanorange/detail/ranges/concepts.hpp +++ b/include/nanorange/detail/ranges/concepts.hpp @@ -14,26 +14,7 @@ #include #include - -// Avoid dragging in the large and headers -// This is technically undefined behaviour: define the symbol -// NANORANGE_NO_STD_FORWARD_DECLARATIONS -// to enforce standard-compliant mode -#ifndef NANORANGE_NO_STD_FORWARD_DECLARATIONS -NANO_BEGIN_NAMESPACE_STD -template class basic_string_view; -template class set; -template class multiset; -template class unordered_set; -template class unordered_multiset; -template class match_results; -NANO_END_NAMESPACE_STD -#else #include -#include -#include -#include -#endif NANO_BEGIN_NAMESPACE @@ -67,47 +48,12 @@ NANO_CONCEPT sized_range = // [range.views] struct view_base { }; -namespace detail { - -template -inline constexpr bool is_std_non_view = false; - -template -inline constexpr bool is_std_non_view> = true; - -template -inline constexpr bool is_std_non_view> = true; - -template -inline constexpr bool is_std_non_view> = true; - -template -inline constexpr bool is_std_non_view> = true; - -template -inline constexpr bool is_std_non_view> = true; - -template -inline constexpr bool is_std_non_view> = true; - template -constexpr bool enable_view_helper() -{ - if constexpr (derived_from) { - return true; - } else if constexpr (is_std_non_view) { - return false; - } else if constexpr (range && range) { - return same_as, range_reference_t>; - } else { - return true; - } -} +inline constexpr bool enable_view = derived_from; -} - -template -inline constexpr bool enable_view = detail::enable_view_helper(); +// Special-case std::string_view +template +inline constexpr bool enable_view> = true; template NANO_CONCEPT view = range && semiregular && enable_view; diff --git a/include/nanorange/views/split.hpp b/include/nanorange/views/split.hpp index 433efeb..22ece2a 100644 --- a/include/nanorange/views/split.hpp +++ b/include/nanorange/views/split.hpp @@ -116,7 +116,7 @@ struct split_view : view_interface> { using iterator_category = detail::conditional_t< forward_range, forward_iterator_tag, input_iterator_tag>; - struct value_type { + struct value_type : view_interface { private: outer_iterator i_ = outer_iterator(); diff --git a/test/concepts/ranges.cpp b/test/concepts/ranges.cpp index 00a49bd..e42dfc8 100644 --- a/test/concepts/ranges.cpp +++ b/test/concepts/ranges.cpp @@ -170,7 +170,7 @@ void ridiculously_exhaustive_range_property_test() { // FIXME: This no longer asserts with P0970. Is that intentional? // CONCEPT_ASSERT(!models::SizedRange); //CONCEPT_ASSERT(!models::_ContainerLike); - CONCEPT_ASSERT(models::view); + //CONCEPT_ASSERT(models::view); CONCEPT_ASSERT(models::same_as, I>); CONCEPT_ASSERT(models::same_as, I>); @@ -196,7 +196,7 @@ void ridiculously_exhaustive_range_property_test() { CONCEPT_ASSERT(models::range); CONCEPT_ASSERT(models::sized_range); //CONCEPT_ASSERT(!models::_ContainerLike); - CONCEPT_ASSERT(models::view); + //CONCEPT_ASSERT(models::view); CONCEPT_ASSERT(models::same_as, CI>); CONCEPT_ASSERT(models::same_as, CI>); @@ -254,7 +254,7 @@ void ridiculously_exhaustive_range_property_test() { CONCEPT_ASSERT(models::range); CONCEPT_ASSERT(models::sized_range); //CONCEPT_ASSERT(!models::_ContainerLike); - CONCEPT_ASSERT(models::view); + //CONCEPT_ASSERT(models::view); CONCEPT_ASSERT(models::same_as, I>); CONCEPT_ASSERT(models::same_as, I>); @@ -279,7 +279,7 @@ void ridiculously_exhaustive_range_property_test() { CONCEPT_ASSERT(models::range); CONCEPT_ASSERT(models::sized_range); //CONCEPT_ASSERT(!models::_ContainerLike); - CONCEPT_ASSERT(models::view); + //CONCEPT_ASSERT(models::view); CONCEPT_ASSERT(models::same_as, CI>); CONCEPT_ASSERT(models::same_as, CI>); @@ -337,7 +337,7 @@ void ridiculously_exhaustive_range_property_test() { CONCEPT_ASSERT(models::range); CONCEPT_ASSERT(!models::sized_range); //CONCEPT_ASSERT(!models::_ContainerLike); - CONCEPT_ASSERT(models::view); + //CONCEPT_ASSERT(models::view); CONCEPT_ASSERT(models::same_as, I>); CONCEPT_ASSERT(models::same_as, I>); @@ -362,7 +362,7 @@ void ridiculously_exhaustive_range_property_test() { CONCEPT_ASSERT(models::range); CONCEPT_ASSERT(!models::sized_range); //CONCEPT_ASSERT(!models::_ContainerLike); - CONCEPT_ASSERT(models::view); + //CONCEPT_ASSERT(models::view); CONCEPT_ASSERT(models::same_as, CI>); CONCEPT_ASSERT(models::same_as, CI>); @@ -414,7 +414,7 @@ void ridiculously_exhaustive_range_property_test() { CONCEPT_ASSERT(models::range); CONCEPT_ASSERT(models::range); - CONCEPT_ASSERT(models::view); + //CONCEPT_ASSERT(models::view); CONCEPT_ASSERT(!models::view); CONCEPT_ASSERT(!models::view); CONCEPT_ASSERT(!models::range); @@ -442,7 +442,7 @@ ns::iterator_t complicated_algorithm(R&& r) { } template -struct array_view { +struct array_view : nano::view_base { T* first_; std::size_t n_; diff --git a/test/utility/concepts.cpp b/test/utility/concepts.cpp index 7647387..483e79c 100644 --- a/test/utility/concepts.cpp +++ b/test/utility/concepts.cpp @@ -267,7 +267,7 @@ static_assert( ranges::concepts::View >::value, "");*/ -struct myview { +struct myview : ranges::view_base { const char *begin(); const char *end(); };