Skip to content

Commit

Permalink
Remove the enable_view heuristic (#1455)
Browse files Browse the repository at this point in the history
This is to more closely harmonize range-v3 with C++20's std::ranges. Refers to cplusplus/nbballot#278
  • Loading branch information
ericniebler authored Mar 20, 2020
1 parent 794c2e7 commit 6103268
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 132 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@
"__string": "cpp",
"algorithm": "cpp",
"codecvt": "cpp",
"valarray": "cpp"
"valarray": "cpp",
"version": "cpp"
},
"C_Cpp.configurationWarnings": "Disabled"
}
36 changes: 20 additions & 16 deletions include/concepts/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,38 +1167,42 @@ namespace concepts
convertible_to<T, T>;

template<typename T>
CPP_concept_bool copy_constructible =
move_constructible<T> &&
CPP_concept_fragment(copy_constructible_,
requires()(0) &&
constructible_from<T, T &> &&
constructible_from<T, T const &> &&
constructible_from<T, T const> &&
convertible_to<T &, T> &&
convertible_to<T const &, T> &&
convertible_to<T const, T>;
convertible_to<T const, T>
);
template<typename T>
CPP_concept_bool copy_constructible =
move_constructible<T> &&
CPP_fragment(concepts::copy_constructible_, T);

template<typename T>
CPP_concept_fragment(move_assignable_,
requires()(0) &&
assignable_from<T &, T>
);
template<typename T>
CPP_concept_bool movable =
std::is_object<T>::value &&
move_constructible<T> &&
assignable_from<T &, T> &&
CPP_fragment(concepts::move_assignable_, T) &&
swappable<T>;

template<typename T>
CPP_concept_fragment(copy_assignable_,
requires()(0) &&
assignable_from<T &, T const &>
);
template<typename T>
CPP_concept_bool copyable =
copy_constructible<T> &&
movable<T> &&
assignable_from<T &, T const &>;

#if !CPP_CXX_CONCEPTS
template<>
CPP_concept_bool copy_constructible<void> = false;

template<>
CPP_concept_bool movable<void> = false;

template<>
CPP_concept_bool copyable<void> = false;
#endif
CPP_fragment(concepts::copy_assignable_, T);

template<typename T>
CPP_concept_bool semiregular =
Expand Down
13 changes: 7 additions & 6 deletions include/range/v3/iterator/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,22 +226,23 @@ namespace ranges
weakly_incrementable<I> &&
CPP_fragment(ranges::incrementable_, I);

template<typename I>
CPP_concept_fragment(input_or_output_iterator_,
requires()(0) &&
detail::dereferenceable_<I&>
);

template<typename I>
CPP_concept_bool input_or_output_iterator =
weakly_incrementable<I> &&
detail::dereferenceable_<I&>;
CPP_fragment(ranges::input_or_output_iterator_, I);

template<typename S, typename I>
CPP_concept_bool sentinel_for =
semiregular<S> &&
input_or_output_iterator<I> &&
detail::weakly_equality_comparable_with_<S, I>;

#if !CPP_CXX_CONCEPTS
template<>
CPP_concept_bool input_or_output_iterator<void> = false;
#endif

namespace defer
{
template<typename S, typename I>
Expand Down
32 changes: 27 additions & 5 deletions include/range/v3/range/access.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@
#include <initializer_list>
#include <iterator>
#include <limits>
#ifdef __has_include
#if __has_include(<string_view>)
#include <string_view>
#endif
#endif
#include <utility>

#include <range/v3/range_fwd.hpp>
Expand All @@ -32,6 +27,28 @@
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>

#ifndef RANGES_NO_STD_FORWARD_DECLARATIONS
// Non-portable forward declarations of standard library components
RANGES_BEGIN_NAMESPACE_STD
RANGES_BEGIN_NAMESPACE_VERSION
template<typename ElementType, size_t Extent>
class span;

template<typename CharT, typename Traits>
class basic_string_view;
RANGES_END_NAMESPACE_VERSION
RANGES_END_NAMESPACE_STD
#else
#ifdef __has_include
#if __has_include(<span>)
#include <span>
#endif
#if __has_include(<string_view>)
#include <string_view>
#endif
#endif
#endif

#include <range/v3/detail/disable_warnings.hpp>

namespace ranges
Expand All @@ -42,6 +59,11 @@ namespace ranges
enable_safe_range<std::basic_string_view<CharT, Traits>> = true;
#endif

#if defined(__cpp_lib_span) && __cpp_lib_span > 0
template<class T, std::size_t N>
RANGES_INLINE_VAR constexpr bool enable_safe_range<std::span<T, N>> = true;
#endif

namespace detail
{
template<typename T>
Expand Down
134 changes: 32 additions & 102 deletions include/range/v3/range/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,35 +32,25 @@
#include <range/v3/range/traits.hpp>

#ifndef RANGES_NO_STD_FORWARD_DECLARATIONS
// Non-portable forward declarations of standard containers
// Non-portable forward declarations of standard library components
RANGES_BEGIN_NAMESPACE_STD
RANGES_BEGIN_NAMESPACE_CONTAINER
template<typename Key,
typename Compare /*= less<Key>*/,
typename Alloc /*= allocator<Key>*/>
class set;

template<typename Key,
typename Compare /*= less<Key>*/,
typename Alloc /*= allocator<Key>*/>
class multiset;

template<typename Key,
typename Hash /*= hash<Key>*/,
typename Pred /*= equal_to<Key>*/,
typename Alloc /*= allocator<Key>*/>
class unordered_set;

template<typename Key,
typename Hash /*= hash<Key>*/,
typename Pred /*= equal_to<Key>*/,
typename Alloc /*= allocator<Key>*/>
class unordered_multiset;
RANGES_END_NAMESPACE_CONTAINER
RANGES_BEGIN_NAMESPACE_VERSION
template<typename ElementType, size_t Extent>
class span;

template<typename CharT, typename Traits>
class basic_string_view;
RANGES_END_NAMESPACE_VERSION
RANGES_END_NAMESPACE_STD
#else
#include <set>
#include <unordered_set>
#ifdef __has_include
#if __has_include(<span>)
#include <span>
#endif
#if __has_include(<string_view>)
#include <string_view>
#endif
#endif
#endif

#include <range/v3/detail/disable_warnings.hpp>
Expand Down Expand Up @@ -186,90 +176,30 @@ namespace ranges
// clang-format on

/// \cond
namespace detail
namespace ext
{
struct enable_view_helper_
{
bool result_;

template<typename T>
static constexpr auto test(T const *) -> CPP_ret(bool)( //
requires range<T> && range<T const>)
{
return RANGES_IS_SAME(iter_reference_t<iterator_t<T>>,
iter_reference_t<iterator_t<T const>>);
}
static constexpr auto test(void const *) -> bool
{
return true;
}
template<typename T>
constexpr enable_view_helper_(T const * p)
: result_(enable_view_helper_::test(p))
{}
};
constexpr bool enable_view_impl_(...)
{
return false;
}
constexpr bool enable_view_impl_(view_base const *)
{
return true;
}
constexpr bool enable_view_impl_(enable_view_helper_ ev)
{
return ev.result_;
}
template<typename T>
constexpr bool enable_view_impl_(std::initializer_list<T> const *)
{
return false;
}
template<typename Key, typename Compare, typename Alloc>
constexpr bool enable_view_impl_(std::set<Key, Compare, Alloc> const *)
{
return false;
}
template<typename Key, typename Compare, typename Alloc>
constexpr bool enable_view_impl_(std::multiset<Key, Compare, Alloc> const *)
{
return false;
}
template<typename Key, typename Hash, typename Pred, typename Alloc>
constexpr bool enable_view_impl_(
std::unordered_set<Key, Hash, Pred, Alloc> const *)
{
return false;
}
template<typename Key, typename Hash, typename Pred, typename Alloc>
constexpr bool enable_view_impl_(
std::unordered_multiset<Key, Hash, Pred, Alloc> const *)
{
return false;
}
// BUGBUG TODO
// template<typename BidiIter, typename Alloc>
// constexpr bool enable_view_impl_(std::match_results<BidiIter, Alloc> const *)
// {
// return false;
// }
template<typename T>
constexpr T const * nullptr_(int)
{
return nullptr;
}
template<typename T>
constexpr int nullptr_(long)
{
return 0;
}
struct enable_view
: std::is_base_of<view_base, T>
{};
} // namespace detail
/// \endcond

// Specialize this if the default is wrong.
template<typename T>
RANGES_INLINE_VAR constexpr bool enable_view =
detail::enable_view_impl_(detail::nullptr_<T>(0));
ext::enable_view<T>::value;

#if defined(__cpp_lib_string_view) && __cpp_lib_string_view > 0
template<typename Char, typename Traits>
RANGES_INLINE_VAR constexpr bool enable_view<std::basic_string_view<Char, Traits>> =
true;
#endif

#if defined(__cpp_lib_span) && __cpp_lib_span > 0
template<typename T, std::size_t N>
RANGES_INLINE_VAR constexpr bool enable_view<std::span<T, N>> = N + 1 < 2;
#endif

///
/// View concepts below
Expand Down
2 changes: 1 addition & 1 deletion test/debug_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <range/v3/utility/swap.hpp>

template<typename T, bool Sized = true>
struct debug_input_view
struct debug_input_view : ranges::view_base
{
static_assert(std::is_object<T>::value, "");

Expand Down
2 changes: 1 addition & 1 deletion test/utility/concepts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ static_assert(ranges::view_<ranges::istream_view<int>>, "");
static_assert(!ranges::common_range<ranges::istream_view<int>>, "");
static_assert(!ranges::sized_range<ranges::istream_view<int>>, "");

struct myview {
struct myview : ranges::view_base {
const char *begin();
const char *end();
};
Expand Down

0 comments on commit 6103268

Please sign in to comment.