blob: e98513e2b945f2f4ccb61ade363400b1854d205d [file] [log] [blame]
/*
* Copyright (c) 2023 NVIDIA Corporation
*
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://llvm.org/LICENSE.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "__config.hpp"
#include "__type_traits.hpp"
#if 0 // STDEXEC_HAS_STD_RANGES()
#include <ranges>
namespace stdexec::ranges {
using std::ranges::begin;
using std::ranges::end;
using std::ranges::range_value_t;
using std::ranges::range_reference_t;
using std::ranges::iterator_t;
using std::ranges::sentinel_t;
}
#else
#include <iterator>
namespace stdexec::ranges
{
namespace __detail
{
void begin();
void end();
template <class _Ty>
concept __has_member_begin =
requires(_Ty&& __v) { static_cast<_Ty&&>(__v).begin(); };
template <class _Ty>
concept __has_free_begin =
__has_member_begin<_Ty> ||
requires(_Ty&& __v) { begin((static_cast<_Ty&&>(__v))); };
template <class _Ty>
concept __has_member_end =
requires(_Ty&& __v) { static_cast<_Ty&&>(__v).end(); };
template <class _Ty>
concept __has_free_end =
__has_member_end<_Ty> ||
requires(_Ty&& __v) { end((static_cast<_Ty&&>(__v))); };
struct __begin_t
{
template <class _Range>
requires __has_member_begin<_Range>
auto operator()(_Range&& __rng) const
noexcept(noexcept((static_cast<_Range&&>(__rng)).begin()))
-> decltype((static_cast<_Range&&>(__rng)).begin())
{
return static_cast<_Range&&>(__rng).begin();
}
template <class _Range>
requires __has_free_begin<_Range>
auto operator()(_Range&& __rng) const
noexcept(noexcept(begin((static_cast<_Range&&>(__rng)))))
-> decltype(begin((static_cast<_Range&&>(__rng))))
{
return begin((static_cast<_Range&&>(__rng)));
}
};
struct __end_t
{
template <class _Range>
requires __has_member_end<_Range>
auto operator()(_Range&& __rng) const
noexcept(noexcept((static_cast<_Range&&>(__rng)).end()))
-> decltype((static_cast<_Range&&>(__rng)).end())
{
return static_cast<_Range&&>(__rng).end();
}
template <class _Range>
requires __has_free_end<_Range>
auto operator()(_Range&& __rng) const
noexcept(noexcept(end((static_cast<_Range&&>(__rng)))))
-> decltype(end((static_cast<_Range&&>(__rng))))
{
return end((static_cast<_Range&&>(__rng)));
}
};
} // namespace __detail
inline constexpr __detail::__begin_t begin{};
inline constexpr __detail::__end_t end{};
template <class _Range>
using iterator_t = decltype(begin((__declval<_Range>())));
template <class _Range>
using sentinel_t = decltype(end((__declval<_Range>())));
template <class _Range>
using range_reference_t = decltype(*begin((__declval<_Range>())));
template <class _Range>
using range_value_t =
typename std::iterator_traits<iterator_t<_Range>>::value_type;
} // namespace stdexec::ranges
#endif