Skip to content

Commit

Permalink
Implement the projected helper struct
Browse files Browse the repository at this point in the history
  • Loading branch information
miscco committed Sep 13, 2023
1 parent f2b931b commit 3ae6494
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// projected

#include <cuda/std/iterator>

#include <cuda/std/concepts>
#include <cuda/std/functional>

#include "test_iterators.h"

using IntPtr = cuda::std::projected<int const*, cuda::std::identity>;
static_assert(cuda::std::same_as<IntPtr::value_type, int>);
static_assert(cuda::std::same_as<decltype(*cuda::std::declval<IntPtr>()), int const&>);
static_assert(cuda::std::same_as<cuda::std::iter_difference_t<IntPtr>, cuda::std::ptrdiff_t>);

struct S { };

using Cpp17InputIterator = cuda::std::projected<cpp17_input_iterator<S*>, int S::*>;
static_assert(cuda::std::same_as<Cpp17InputIterator::value_type, int>);
static_assert(cuda::std::same_as<decltype(*cuda::std::declval<Cpp17InputIterator>()), int&>);
static_assert(cuda::std::same_as<cuda::std::iter_difference_t<Cpp17InputIterator>, cuda::std::ptrdiff_t>);

using Cpp20InputIterator = cuda::std::projected<cpp20_input_iterator<S*>, int S::*>;
static_assert(cuda::std::same_as<Cpp20InputIterator::value_type, int>);
static_assert(cuda::std::same_as<decltype(*cuda::std::declval<Cpp20InputIterator>()), int&>);
static_assert(cuda::std::same_as<cuda::std::iter_difference_t<Cpp20InputIterator>, cuda::std::ptrdiff_t>);

using ForwardIterator = cuda::std::projected<forward_iterator<S*>, int (S::*)()>;
static_assert(cuda::std::same_as<ForwardIterator::value_type, int>);
static_assert(cuda::std::same_as<decltype(*cuda::std::declval<ForwardIterator>()), int>);
static_assert(cuda::std::same_as<cuda::std::iter_difference_t<ForwardIterator>, cuda::std::ptrdiff_t>);

using BidirectionalIterator = cuda::std::projected<bidirectional_iterator<S*>, S* (S::*)() const>;
static_assert(cuda::std::same_as<BidirectionalIterator::value_type, S*>);
static_assert(cuda::std::same_as<decltype(*cuda::std::declval<BidirectionalIterator>()), S*>);
static_assert(cuda::std::same_as<cuda::std::iter_difference_t<BidirectionalIterator>, cuda::std::ptrdiff_t>);

using RandomAccessIterator = cuda::std::projected<random_access_iterator<S*>, S && (S::*)()>;
static_assert(cuda::std::same_as<RandomAccessIterator::value_type, S>);
static_assert(cuda::std::same_as<decltype(*cuda::std::declval<RandomAccessIterator>()), S&&>);
static_assert(cuda::std::same_as<cuda::std::iter_difference_t<RandomAccessIterator>, cuda::std::ptrdiff_t>);

using ContiguousIterator = cuda::std::projected<contiguous_iterator<S*>, S& (S::*)() const>;
static_assert(cuda::std::same_as<ContiguousIterator::value_type, S>);
static_assert(cuda::std::same_as<decltype(*cuda::std::declval<ContiguousIterator>()), S&>);
static_assert(cuda::std::same_as<cuda::std::iter_difference_t<ContiguousIterator>, cuda::std::ptrdiff_t>);

#if TEST_STD_VER > 17
template <class I, class F>
constexpr bool projectable = requires {
typename cuda::std::projected<I, F>;
};
#else
template <class I, class F>
_LIBCUDACXX_CONCEPT_FRAGMENT(
projectable_,
requires() //
(typename(cuda::std::projected<I, F>)));

template <class I, class F>
_LIBCUDACXX_CONCEPT projectable = _LIBCUDACXX_FRAGMENT(projectable_, I, F);
#endif

static_assert(!projectable<int, void (*)(int)>); // int isn't indirectly_readable
static_assert(!projectable<S, void (*)(int)>); // S isn't weakly_incrementable
static_assert(!projectable<int*, void(int)>); // void(int) doesn't satisfy indirectly_regular_unary_invcable

int main(int, char**)
{
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ set(files
__iterator/ostreambuf_iterator.h
__iterator/permutable.h
__iterator/prev.h
__iterator/projected.h
__iterator/readable_traits.h
__iterator/reverse_access.h
__iterator/reverse_iterator.h
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCUDACXX___ITERATOR_PROJECTED_H
#define _LIBCUDACXX___ITERATOR_PROJECTED_H

#ifndef __cuda_std__
#include <__config>
#endif // __cuda_std__

#include "../__iterator/concepts.h"
#include "../__iterator/incrementable_traits.h"
#include "../__type_traits/enable_if.h"
#include "../__type_traits/remove_cvref.h"

#if defined(_LIBCUDACXX_USE_PRAGMA_GCC_SYSTEM_HEADER)
#pragma GCC system_header
#endif

_LIBCUDACXX_BEGIN_NAMESPACE_STD

#if _LIBCUDACXX_STD_VER > 14

_LIBCUDACXX_TEMPLATE(class _It, class _Proj)
(requires indirectly_readable<_It> _LIBCUDACXX_AND indirectly_regular_unary_invocable<_Proj, _It>)
struct projected {
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
_LIBCUDACXX_INLINE_VISIBILITY indirect_result_t<_Proj&, _It> operator*() const; // not defined
};

#if _LIBCUDACXX_STD_VER > 17
template<weakly_incrementable _It, class _Proj>
struct incrementable_traits<projected<_It, _Proj>> {
using difference_type = iter_difference_t<_It>;
};
#else
template<class _It, class _Proj>
struct incrementable_traits<projected<_It, _Proj>, enable_if_t<weakly_incrementable<_It>>> {
using difference_type = iter_difference_t<_It>;
};
#endif // _LIBCUDACXX_STD_VER > 17

#endif // _LIBCUDACXX_STD_VER > 14

_LIBCUDACXX_END_NAMESPACE_STD

#endif // _LIBCUDACXX___ITERATOR_PROJECTED_H
1 change: 1 addition & 0 deletions libcudacxx/include/cuda/std/detail/libcxx/include/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
#include "__iterator/ostreambuf_iterator.h"
#include "__iterator/permutable.h"
#include "__iterator/prev.h"
#include "__iterator/projected.h"
#include "__iterator/readable_traits.h"
#include "__iterator/reverse_access.h"
#include "__iterator/reverse_iterator.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// projected

#include <iterator>

#include <concepts>
#include <functional>

#include "test_iterators.h"

using IntPtr = std::projected<int const*, std::identity>;
static_assert(std::same_as<IntPtr::value_type, int>);
static_assert(std::same_as<decltype(*std::declval<IntPtr>()), int const&>);
static_assert(std::same_as<std::iter_difference_t<IntPtr>, std::ptrdiff_t>);

struct S { };

using Cpp17InputIterator = std::projected<cpp17_input_iterator<S*>, int S::*>;
static_assert(std::same_as<Cpp17InputIterator::value_type, int>);
static_assert(std::same_as<decltype(*std::declval<Cpp17InputIterator>()), int&>);
static_assert(std::same_as<std::iter_difference_t<Cpp17InputIterator>, std::ptrdiff_t>);

using Cpp20InputIterator = std::projected<cpp20_input_iterator<S*>, int S::*>;
static_assert(std::same_as<Cpp20InputIterator::value_type, int>);
static_assert(std::same_as<decltype(*std::declval<Cpp20InputIterator>()), int&>);
static_assert(std::same_as<std::iter_difference_t<Cpp20InputIterator>, std::ptrdiff_t>);

using ForwardIterator = std::projected<forward_iterator<S*>, int (S::*)()>;
static_assert(std::same_as<ForwardIterator::value_type, int>);
static_assert(std::same_as<decltype(*std::declval<ForwardIterator>()), int>);
static_assert(std::same_as<std::iter_difference_t<ForwardIterator>, std::ptrdiff_t>);

using BidirectionalIterator = std::projected<bidirectional_iterator<S*>, S* (S::*)() const>;
static_assert(std::same_as<BidirectionalIterator::value_type, S*>);
static_assert(std::same_as<decltype(*std::declval<BidirectionalIterator>()), S*>);
static_assert(std::same_as<std::iter_difference_t<BidirectionalIterator>, std::ptrdiff_t>);

using RandomAccessIterator = std::projected<random_access_iterator<S*>, S && (S::*)()>;
static_assert(std::same_as<RandomAccessIterator::value_type, S>);
static_assert(std::same_as<decltype(*std::declval<RandomAccessIterator>()), S&&>);
static_assert(std::same_as<std::iter_difference_t<RandomAccessIterator>, std::ptrdiff_t>);

using ContiguousIterator = std::projected<contiguous_iterator<S*>, S& (S::*)() const>;
static_assert(std::same_as<ContiguousIterator::value_type, S>);
static_assert(std::same_as<decltype(*std::declval<ContiguousIterator>()), S&>);
static_assert(std::same_as<std::iter_difference_t<ContiguousIterator>, std::ptrdiff_t>);

template <class I, class F>
constexpr bool projectable = requires {
typename std::projected<I, F>;
};

static_assert(!projectable<int, void (*)(int)>); // int isn't indirectly_readable
static_assert(!projectable<S, void (*)(int)>); // S isn't weakly_incrementable
static_assert(!projectable<int*, void(int)>); // void(int) doesn't satisfy indirectly_regular_unary_invcable

int main(int, char**) {
return 0;
}

0 comments on commit 3ae6494

Please sign in to comment.