Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
213 lines (169 sloc) 5.51 KB
// nanorange/detail/ranges/begin_end.hpp
//
// Copyright (c) 2018 Tristan Brindle (tcbrindle at gmail dot com)
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef NANORANGE_DETAIL_RANGES_BEGIN_END_HPP_INCLUDED
#define NANORANGE_DETAIL_RANGES_BEGIN_END_HPP_INCLUDED
#include <nanorange/detail/functional/decay_copy.hpp>
#include <nanorange/detail/iterator/concepts.hpp>
#ifdef NANO_HAVE_CPP17
#include <string_view>
#endif
NANO_BEGIN_NAMESPACE
// [range.access.begin]
namespace detail {
namespace begin_ {
template <typename T>
void begin(T&&) = delete;
template <typename T>
void begin(std::initializer_list<T>&&) = delete;
struct fn {
private:
template <typename T, std::size_t N>
static constexpr void impl(T(&&)[N], priority_tag<2>) = delete;
template <typename T, std::size_t N>
static constexpr auto impl(T (&t)[N], priority_tag<2>) noexcept
-> decltype((t) + 0)
{
return (t) + 0;
}
// Specialisation for rvalue string_views in C++17, as we can't add
// functions to namespace std
#ifdef NANO_HAVE_CPP17
template <typename C, typename T>
static constexpr auto
impl(std::basic_string_view<C, T> sv, priority_tag<2>) noexcept
-> decltype(sv.begin())
{
return sv.begin();
}
#endif
template <typename T>
static constexpr auto
impl(T& t, priority_tag<1>) noexcept(noexcept(decay_copy(t.begin())))
-> std::enable_if_t<Iterator<decltype(decay_copy(t.begin()))>,
decltype(decay_copy(t.begin()))>
{
return decay_copy(t.begin());
}
template <typename T>
static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
noexcept(decay_copy(begin(std::forward<T>(t)))))
-> std::enable_if_t<
Iterator<decltype(decay_copy(begin(std::forward<T>(t))))>,
decltype(decay_copy(begin(std::forward<T>(t))))>
{
return decay_copy(begin(std::forward<T>(t)));
}
public:
template <typename T>
constexpr auto operator()(T&& t) const
noexcept(noexcept(fn::impl(std::forward<T>(t), priority_tag<2>{})))
-> decltype(fn::impl(std::forward<T>(t), priority_tag<2>{}))
{
return fn::impl(std::forward<T>(t), priority_tag<2>{});
}
};
} // namespace begin_
} // namespace detail
NANO_INLINE_VAR(detail::begin_::fn, begin)
namespace detail {
namespace end_ {
template <typename T>
void end(T&&) = delete;
template <typename T>
void end(std::initializer_list<T>&&) = delete;
struct fn {
private:
template <typename T, std::size_t N>
static constexpr void impl(T(&&)[N], priority_tag<2>) = delete;
template <typename T, std::size_t N>
static constexpr auto impl(T (&t)[N], priority_tag<2>) noexcept
-> decltype(t + N)
{
return t + N;
}
#ifdef NANO_HAVE_CPP17
template <typename C, typename T>
static constexpr auto
impl(std::basic_string_view<C, T> sv, priority_tag<2>) noexcept
-> decltype(sv.end())
{
return sv.end();
}
#endif
template <typename T,
typename S = decltype(decay_copy(std::declval<T&>().end())),
typename I = decltype(ranges::begin(std::declval<T&>()))>
static constexpr auto
impl(T& t, priority_tag<1>) noexcept(noexcept(decay_copy(t.end())))
-> std::enable_if_t<Sentinel<S, I>, decltype(decay_copy(t.end()))>
{
return decay_copy(t.end());
}
template <typename T,
typename S = decltype(decay_copy(end(std::declval<T>()))),
typename I = decltype(ranges::begin(std::declval<T>()))>
static constexpr auto impl(T&& t, priority_tag<0>) noexcept(
noexcept(decay_copy(end(std::forward<T>(t)))))
-> std::enable_if_t<Sentinel<S, I>, S>
{
return decay_copy(end(std::forward<T>(t)));
}
public:
template <typename T>
constexpr auto operator()(T&& t) const
noexcept(noexcept(fn::impl(std::forward<T>(t), priority_tag<2>{})))
-> decltype(fn::impl(std::forward<T>(t), priority_tag<2>{}))
{
return fn::impl(std::forward<T>(t), priority_tag<2>{});
}
};
} // namespace end_
} // namespace detail
NANO_INLINE_VAR(detail::end_::fn, end)
// [range.access.cbegin]
namespace detail {
namespace cbegin_ {
struct fn {
template <typename T>
constexpr auto operator()(const T& t) const
noexcept(noexcept(ranges::begin(t))) -> decltype(ranges::begin(t))
{
return ranges::begin(t);
}
template <typename T>
constexpr auto operator()(const T&& t) const
noexcept(noexcept(ranges::begin(static_cast<const T&&>(t))))
-> decltype(ranges::begin(static_cast<const T&&>(t)))
{
return ranges::begin(static_cast<const T&&>(t));
}
};
} // namespace cbegin_
} // namespace detail
NANO_INLINE_VAR(detail::cbegin_::fn, cbegin)
// [ranges.access.cend]
namespace detail {
namespace cend_ {
struct fn {
template <typename T>
constexpr auto operator()(const T& t) const
noexcept(noexcept(ranges::end(t))) -> decltype(ranges::end(t))
{
return ranges::end(t);
}
template <typename T>
constexpr auto operator()(const T&& t) const
noexcept(noexcept(ranges::end(static_cast<const T&&>(t))))
-> decltype(ranges::end(static_cast<const T&&>(t)))
{
return ranges::end(static_cast<const T&&>(t));
}
};
} // namespace cend_
} // namespace detail
NANO_INLINE_VAR(detail::cend_::fn, cend)
NANO_END_NAMESPACE
#endif
You can’t perform that action at this time.