Skip to content

Commit

Permalink
Use niebloids for {cr}begin / and {cr}end
Browse files Browse the repository at this point in the history
We must avoid ambiguities with the std:: overloads. Also MSVC does not like the SFINAE workaround
  • Loading branch information
miscco committed May 3, 2024
1 parent d9b5426 commit 689f5dd
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 177 deletions.
176 changes: 86 additions & 90 deletions libcudacxx/include/cuda/std/__iterator/access.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,113 +21,109 @@
# pragma system_header
#endif // no system header

#include <cuda/std/__type_traits/enable_if.h>
#include <cuda/std/__type_traits/is_same.h>
#include <cuda/std/__utility/declval.h>
#include <cuda/std/cstddef>
#include <cuda/std/initializer_list>

_LIBCUDACXX_BEGIN_NAMESPACE_STD

// We need to detect whether there is already a free function begin / end that would end up being ambiguous.
// This can happen when a type pulls in both namespace std and namespace cuda::std via ADL.
// In that case we are always safe to just not do anything because that type must be host only.
namespace __detect_ambiguous_access
namespace __begin
{
struct __no_adl_found
{};
template <class _Tp, size_t _Np>
_LIBCUDACXX_INLINE_VISIBILITY auto __begin(_Tp (&__array)[_Np]) -> decltype(begin(__array));
template <class _Cont>
_LIBCUDACXX_INLINE_VISIBILITY auto __begin(_Cont& __c) -> decltype(begin(__c));
template <class _Cont>
_LIBCUDACXX_INLINE_VISIBILITY auto __begin(const _Cont& __c) -> decltype(begin(__c));
_LIBCUDACXX_INLINE_VISIBILITY auto __begin(...) -> __no_adl_found;
template <class _Cont>
struct __has_no_adl_begin
: is_same<decltype(__detect_ambiguous_access::__begin(_CUDA_VSTD::declval<_Cont>())), __no_adl_found>
{};
template <class _Tp>
struct __has_no_adl_begin<initializer_list<_Tp>&> : true_type
{};
template <class _Tp>
struct __has_no_adl_begin<const initializer_list<_Tp>&> : true_type
{};

template <class _Tp, size_t _Np>
_LIBCUDACXX_INLINE_VISIBILITY auto __end(_Tp (&__array)[_Np]) -> decltype(end(__array));
template <class _Cont>
_LIBCUDACXX_INLINE_VISIBILITY auto __end(_Cont& __c) -> decltype(end(__c));
template <class _Cont>
_LIBCUDACXX_INLINE_VISIBILITY auto __end(const _Cont& __c) -> decltype(end(__c));
_LIBCUDACXX_INLINE_VISIBILITY auto __end(...) -> __no_adl_found;
template <class _Cont>
struct __has_no_adl_end
: is_same<decltype(__detect_ambiguous_access::__end(_CUDA_VSTD::declval<_Cont>())), __no_adl_found>
{};
template <class _Tp>
struct __has_no_adl_end<initializer_list<_Tp>&> : true_type
{};
template <class _Tp>
struct __has_no_adl_end<const initializer_list<_Tp>&> : true_type
{};
} // namespace __detect_ambiguous_access

template <class _Tp, size_t _Np>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto begin(_Tp (&__array)[_Np])
-> __enable_if_t<__detect_ambiguous_access::__has_no_adl_begin<_Tp (&)[_Np]>::value, _Tp*>
struct __fn
{
return __array;
}

template <class _Tp, size_t _Np>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto end(_Tp (&__array)[_Np])
-> __enable_if_t<__detect_ambiguous_access::__has_no_adl_end<_Tp (&)[_Np]>::value, _Tp*>
template <class _Tp, size_t _Np>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 _Tp* operator()(_Tp (&__array)[_Np]) const noexcept
{
return __array;
}

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto operator()(_Cp& __c) const noexcept(noexcept(__c.begin()))
-> decltype(__c.begin())
{
return __c.begin();
}

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto operator()(const _Cp& __c) const
noexcept(noexcept(__c.begin())) -> decltype(__c.begin())
{
return __c.begin();
}
};
} // namespace __begin

inline namespace __cpo
{
return __array + _Np;
}
_LIBCUDACXX_CPO_ACCESSIBILITY auto begin = __begin::__fn{};
} // namespace __cpo

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto begin(_Cp& __c)
-> __enable_if_t<__detect_ambiguous_access::__has_no_adl_begin<_Cp&>::value, decltype(__c.begin())>
namespace __end
{
return __c.begin();
}

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto begin(const _Cp& __c)
-> __enable_if_t<__detect_ambiguous_access::__has_no_adl_begin<const _Cp&>::value, decltype(__c.begin())>
struct __fn
{
return __c.begin();
}

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto end(_Cp& __c)
-> __enable_if_t<__detect_ambiguous_access::__has_no_adl_end<_Cp&>::value, decltype(__c.end())>
{
return __c.end();
}

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto end(const _Cp& __c)
-> __enable_if_t<__detect_ambiguous_access::__has_no_adl_end<const _Cp&>::value, decltype(__c.end())>
template <class _Tp, size_t _Np>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 _Tp* operator()(_Tp (&__array)[_Np]) const noexcept
{
return __array + _Np;
}

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto operator()(_Cp& __c) const noexcept(noexcept(__c.end()))
-> decltype(__c.end())
{
return __c.end();
}

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto operator()(const _Cp& __c) const
noexcept(noexcept(__c.end())) -> decltype(__c.end())
{
return __c.end();
}
};
} // namespace __end

inline namespace __cpo
{
return __c.end();
}
_LIBCUDACXX_CPO_ACCESSIBILITY auto end = __end::__fn{};
} // namespace __cpo

#if _CCCL_STD_VER >= 2014

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto cbegin(const _Cp& __c) -> decltype(_CUDA_VSTD::begin(__c))
namespace __cbegin
{
return _CUDA_VSTD::begin(__c);
}
struct __fn
{
template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto operator()(const _Cp& __c) const
noexcept(noexcept(_CUDA_VSTD::begin(__c))) -> decltype(_CUDA_VSTD::begin(__c))
{
return _CUDA_VSTD::begin(__c);
}
};
} // namespace __cbegin

inline namespace __cpo
{
_LIBCUDACXX_CPO_ACCESSIBILITY auto cbegin = __cbegin::__fn{};
} // namespace __cpo

template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto cend(const _Cp& __c) -> decltype(_CUDA_VSTD::end(__c))
namespace __cend
{
struct __fn
{
template <class _Cp>
_LIBCUDACXX_INLINE_VISIBILITY _CCCL_CONSTEXPR_CXX14 auto operator()(const _Cp& __c) const
noexcept(noexcept(_CUDA_VSTD::end(__c))) -> decltype(_CUDA_VSTD::end(__c))
{
return _CUDA_VSTD::end(__c);
}
};
} // namespace __cend

inline namespace __cpo
{
return _CUDA_VSTD::end(__c);
}
_LIBCUDACXX_CPO_ACCESSIBILITY auto cend = __cend::__fn{};
} // namespace __cpo

#endif // _CCCL_STD_VER >= 2014

Expand Down
Loading

0 comments on commit 689f5dd

Please sign in to comment.