diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/iterator.traits/cxx20_iterator_traits.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/iterator.traits/cxx20_iterator_traits.compile.pass.cpp new file mode 100644 index 00000000000..2cd70069d93 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/iterator.traits/cxx20_iterator_traits.compile.pass.cpp @@ -0,0 +1,569 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// This test uses iterator types from cuda::std::filesystem, which were introduced in macOS 10.15. +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14}} + +// template +// struct iterator_traits; + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wc++17-extensions" +#endif + +#include + +#include +#include +#include + +#include "test_macros.h" + +#include "test_iterators.h" +#include "iterator_traits_cpp17_iterators.h" + +template +inline constexpr bool has_iterator_concept_v = false; + +template +inline constexpr bool has_iterator_concept_v> = true; + +template , int> = 0> +__host__ __device__ constexpr void test_iter_concept() { + static_assert(cuda::std::same_as); +} + +template , int> = 0> +__host__ __device__ constexpr void test_iter_concept() { + static_assert(!has_iterator_concept_v); +} + +template +__host__ __device__ constexpr bool test() { + using Traits = cuda::std::iterator_traits; + static_assert(cuda::std::same_as); + static_assert(cuda::std::same_as); + static_assert(cuda::std::same_as); + static_assert(cuda::std::same_as); + static_assert(cuda::std::same_as); + + test_iter_concept(); + + return true; +} + +template +__host__ __device__ constexpr bool testIOIterator() { + return test(); +} + +template +__host__ __device__ constexpr bool testConst() { + return test(); +} + +template +__host__ __device__ constexpr bool testMutable() { + return test(); +} + +// Standard types. + +// The Standard does not specify whether iterator_traits::iterator_concept +// exists for any particular non-pointer type, we assume it is present +// only for pointers. +// +static_assert(testMutable::iterator, cuda::std::random_access_iterator_tag, int>()); +static_assert(testConst::const_iterator, cuda::std::random_access_iterator_tag, int>()); + +// Local test iterators. + +struct AllMembers { + struct iterator_category {}; + struct value_type {}; + struct difference_type {}; + struct reference {}; + struct pointer {}; +}; +using AllMembersTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct NoPointerMember { + struct iterator_category {}; + struct value_type {}; + struct difference_type {}; + struct reference {}; + // ignored, because NoPointerMember is not a LegacyInputIterator: + __host__ __device__ value_type* operator->() const; +}; +using NoPointerMemberTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct IterConcept { + struct iterator_category {}; + struct value_type {}; + struct difference_type {}; + struct reference {}; + struct pointer {}; + // iterator_traits does NOT pass through the iterator_concept of the type itself. + struct iterator_concept {}; +}; +using IterConceptTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyInput { + struct iterator_category {}; + struct value_type {}; + struct reference { __host__ __device__ operator value_type() const; }; + + __host__ __device__ friend bool operator==(LegacyInput, LegacyInput); +#if TEST_STD_VER < 20 + __host__ __device__ friend bool operator!=(LegacyInput, LegacyInput); +#endif + __host__ __device__ reference operator*() const; + __host__ __device__ LegacyInput& operator++(); + __host__ __device__ LegacyInput operator++(int); +}; +template <> +struct cuda::std::incrementable_traits { + using difference_type = short; +}; +using LegacyInputTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyInputNoValueType { + struct not_value_type {}; + using difference_type = int; // or any signed integral type + struct reference { __host__ __device__ operator not_value_type&() const; }; + + __host__ __device__ friend bool operator==(LegacyInputNoValueType, LegacyInputNoValueType); +#if TEST_STD_VER < 20 + __host__ __device__ friend bool operator!=(LegacyInputNoValueType, LegacyInputNoValueType); +#endif + __host__ __device__ reference operator*() const; + __host__ __device__ LegacyInputNoValueType& operator++(); + __host__ __device__ LegacyInputNoValueType operator++(int); +}; +template <> +struct cuda::std::indirectly_readable_traits { + using value_type = LegacyInputNoValueType::not_value_type; +}; +using LegacyInputNoValueTypeTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyForward { + struct not_value_type {}; + + __host__ __device__ friend bool operator==(LegacyForward, LegacyForward); +#if TEST_STD_VER < 20 + __host__ __device__ friend bool operator!=(LegacyForward, LegacyForward); +#endif + __host__ __device__ const not_value_type& operator*() const; + __host__ __device__ LegacyForward& operator++(); + __host__ __device__ LegacyForward operator++(int); +}; +template <> +struct cuda::std::indirectly_readable_traits { + using value_type = LegacyForward::not_value_type; +}; +template <> +struct cuda::std::incrementable_traits { + using difference_type = short; // or any signed integral type +}; +using LegacyForwardTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyBidirectional { + struct value_type {}; + + __host__ __device__ friend bool operator==(LegacyBidirectional, LegacyBidirectional); +#if TEST_STD_VER < 20 + __host__ __device__ friend bool operator!=(LegacyBidirectional, LegacyBidirectional); +#endif + __host__ __device__ const value_type& operator*() const; + __host__ __device__ LegacyBidirectional& operator++(); + __host__ __device__ LegacyBidirectional operator++(int); + __host__ __device__ LegacyBidirectional& operator--(); + __host__ __device__ LegacyBidirectional operator--(int); + __host__ __device__ friend short operator-(LegacyBidirectional, LegacyBidirectional); +}; +using LegacyBidirectionalTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +// Almost a random access iterator except it is missing operator-(It, It). +struct MinusNotDeclaredIter { + struct value_type {}; + +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + auto operator<=>(const MinusNotDeclaredIter&) const = default; // nvbug3908399 +#else + __host__ __device__ friend bool operator==(const MinusNotDeclaredIter&, const MinusNotDeclaredIter&) noexcept { return true;} + __host__ __device__ friend bool operator!=(const MinusNotDeclaredIter&, const MinusNotDeclaredIter&) noexcept { return true;} + __host__ __device__ friend bool operator<(const MinusNotDeclaredIter&, const MinusNotDeclaredIter&) noexcept { return true;} + __host__ __device__ friend bool operator<=(const MinusNotDeclaredIter&, const MinusNotDeclaredIter&) noexcept { return true;} + __host__ __device__ friend bool operator>(const MinusNotDeclaredIter&, const MinusNotDeclaredIter&) noexcept { return true;} + __host__ __device__ friend bool operator>=(const MinusNotDeclaredIter&, const MinusNotDeclaredIter&) noexcept { return true;} +#endif + + __host__ __device__ const value_type& operator*() const; + __host__ __device__ const value_type& operator[](long) const; + __host__ __device__ MinusNotDeclaredIter& operator++(); + __host__ __device__ MinusNotDeclaredIter operator++(int); + __host__ __device__ MinusNotDeclaredIter& operator--(); + __host__ __device__ MinusNotDeclaredIter operator--(int); + __host__ __device__ MinusNotDeclaredIter& operator+=(long); + __host__ __device__ MinusNotDeclaredIter& operator-=(long); + + // Providing difference_type does not fully compensate for missing operator-(It, It). + __host__ __device__ friend MinusNotDeclaredIter operator-(MinusNotDeclaredIter, int); + __host__ __device__ friend MinusNotDeclaredIter operator+(MinusNotDeclaredIter, int); + __host__ __device__ friend MinusNotDeclaredIter operator+(int, MinusNotDeclaredIter); +}; +template <> +struct cuda::std::incrementable_traits { + using difference_type = short; +}; +using MinusNotDeclaredIterTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct WrongSubscriptReturnType { + struct value_type {}; + +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + auto operator<=>(const WrongSubscriptReturnType&) const = default; // nvbug3908399 +#else + __host__ __device__ friend bool operator==(const WrongSubscriptReturnType&, const WrongSubscriptReturnType&) noexcept { return true;} + __host__ __device__ friend bool operator!=(const WrongSubscriptReturnType&, const WrongSubscriptReturnType&) noexcept { return true;} + __host__ __device__ friend bool operator<(const WrongSubscriptReturnType&, const WrongSubscriptReturnType&) noexcept { return true;} + __host__ __device__ friend bool operator<=(const WrongSubscriptReturnType&, const WrongSubscriptReturnType&) noexcept { return true;} + __host__ __device__ friend bool operator>(const WrongSubscriptReturnType&, const WrongSubscriptReturnType&) noexcept { return true;} + __host__ __device__ friend bool operator>=(const WrongSubscriptReturnType&, const WrongSubscriptReturnType&) noexcept { return true;} +#endif + + // The type of it[n] is not convertible to the type of *it; therefore, this is not random-access. + __host__ __device__ value_type& operator*() const; + __host__ __device__ const value_type& operator[](long) const; + __host__ __device__ WrongSubscriptReturnType& operator++(); + __host__ __device__ WrongSubscriptReturnType operator++(int); + __host__ __device__ WrongSubscriptReturnType& operator--(); + __host__ __device__ WrongSubscriptReturnType operator--(int); + __host__ __device__ WrongSubscriptReturnType& operator+=(long); + __host__ __device__ WrongSubscriptReturnType& operator-=(long); + __host__ __device__ friend short operator-(WrongSubscriptReturnType, WrongSubscriptReturnType); + __host__ __device__ friend WrongSubscriptReturnType operator-(WrongSubscriptReturnType, int); + __host__ __device__ friend WrongSubscriptReturnType operator+(WrongSubscriptReturnType, int); + __host__ __device__ friend WrongSubscriptReturnType operator+(int, WrongSubscriptReturnType); +}; +using WrongSubscriptReturnTypeTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyRandomAccess { + struct value_type {}; + + __host__ __device__ friend bool operator==(LegacyRandomAccess, LegacyRandomAccess); +#if TEST_STD_VER < 20 + __host__ __device__ friend bool operator!=(LegacyRandomAccess, LegacyRandomAccess); +#endif + __host__ __device__ friend bool operator<(LegacyRandomAccess, LegacyRandomAccess); + __host__ __device__ friend bool operator<=(LegacyRandomAccess, LegacyRandomAccess); + __host__ __device__ friend bool operator>(LegacyRandomAccess, LegacyRandomAccess); + __host__ __device__ friend bool operator>=(LegacyRandomAccess, LegacyRandomAccess); + __host__ __device__ const value_type& operator*() const; + __host__ __device__ const value_type& operator[](long) const; + __host__ __device__ LegacyRandomAccess& operator++(); + __host__ __device__ LegacyRandomAccess operator++(int); + __host__ __device__ LegacyRandomAccess& operator--(); + __host__ __device__ LegacyRandomAccess operator--(int); + __host__ __device__ LegacyRandomAccess& operator+=(long); + __host__ __device__ LegacyRandomAccess& operator-=(long); + __host__ __device__ friend short operator-(LegacyRandomAccess, LegacyRandomAccess); + __host__ __device__ friend LegacyRandomAccess operator-(LegacyRandomAccess, int); + __host__ __device__ friend LegacyRandomAccess operator+(LegacyRandomAccess, int); + __host__ __device__ friend LegacyRandomAccess operator+(int, LegacyRandomAccess); +}; +using LegacyRandomAccessTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyRandomAccessSpaceship { + struct not_value_type {}; + struct ReferenceConvertible { __host__ __device__ operator not_value_type&() const; }; + +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + auto operator<=>(const LegacyRandomAccessSpaceship&) const = default; // nvbug3908399 +#else + __host__ __device__ friend bool operator==(const LegacyRandomAccessSpaceship&, const LegacyRandomAccessSpaceship&) noexcept { return true;} + __host__ __device__ friend bool operator!=(const LegacyRandomAccessSpaceship&, const LegacyRandomAccessSpaceship&) noexcept { return true;} + __host__ __device__ friend bool operator<(const LegacyRandomAccessSpaceship&, const LegacyRandomAccessSpaceship&) noexcept { return true;} + __host__ __device__ friend bool operator<=(const LegacyRandomAccessSpaceship&, const LegacyRandomAccessSpaceship&) noexcept { return true;} + __host__ __device__ friend bool operator>(const LegacyRandomAccessSpaceship&, const LegacyRandomAccessSpaceship&) noexcept { return true;} + __host__ __device__ friend bool operator>=(const LegacyRandomAccessSpaceship&, const LegacyRandomAccessSpaceship&) noexcept { return true;} +#endif + + __host__ __device__ not_value_type& operator*() const; + __host__ __device__ ReferenceConvertible operator[](long) const; + __host__ __device__ LegacyRandomAccessSpaceship& operator++(); + __host__ __device__ LegacyRandomAccessSpaceship operator++(int); + __host__ __device__ LegacyRandomAccessSpaceship& operator--(); + __host__ __device__ LegacyRandomAccessSpaceship operator--(int); + __host__ __device__ LegacyRandomAccessSpaceship& operator+=(long); + __host__ __device__ LegacyRandomAccessSpaceship& operator-=(long); + __host__ __device__ friend short operator-(LegacyRandomAccessSpaceship, LegacyRandomAccessSpaceship); + __host__ __device__ friend LegacyRandomAccessSpaceship operator-(LegacyRandomAccessSpaceship, int); + __host__ __device__ friend LegacyRandomAccessSpaceship operator+(LegacyRandomAccessSpaceship, int); + __host__ __device__ friend LegacyRandomAccessSpaceship operator+(int, LegacyRandomAccessSpaceship); +}; +template <> +struct cuda::std::indirectly_readable_traits { + using value_type = LegacyRandomAccessSpaceship::not_value_type; +}; +template <> +struct cuda::std::incrementable_traits { + using difference_type = short; // or any signed integral type +}; +using LegacyRandomAccessSpaceshipTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +// For output iterators, value_type, difference_type, and reference may be void. +struct BareLegacyOutput { + struct Empty {}; + __host__ __device__ Empty operator*() const; + __host__ __device__ BareLegacyOutput& operator++(); + __host__ __device__ BareLegacyOutput operator++(int); +}; +using BareLegacyOutputTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +// The operator- means we get difference_type. +struct LegacyOutputWithMinus { + struct Empty {}; + __host__ __device__ Empty operator*() const; + __host__ __device__ LegacyOutputWithMinus& operator++(); + __host__ __device__ LegacyOutputWithMinus operator++(int); + __host__ __device__ friend short operator-(LegacyOutputWithMinus, LegacyOutputWithMinus); + // Lacking operator==, this is a LegacyIterator but not a LegacyInputIterator. +}; +using LegacyOutputWithMinusTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyOutputWithMemberTypes { + struct value_type {}; // ignored + struct reference {}; // ignored + using difference_type = long; + + __host__ __device__ friend bool operator==(LegacyOutputWithMemberTypes, LegacyOutputWithMemberTypes); +#if TEST_STD_VER < 20 + __host__ __device__ friend bool operator!=(LegacyOutputWithMemberTypes, LegacyOutputWithMemberTypes); +#endif + __host__ __device__ reference operator*() const; + __host__ __device__ LegacyOutputWithMemberTypes& operator++(); + __host__ __device__ LegacyOutputWithMemberTypes operator++(int); + __host__ __device__ friend short operator-(LegacyOutputWithMemberTypes, LegacyOutputWithMemberTypes); // ignored + // Since (*it) is not convertible to value_type, this is not a LegacyInputIterator. +}; +using LegacyOutputWithMemberTypesTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +struct LegacyRandomAccessSpecialized { + struct not_value_type {}; + +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + auto operator<=>(const LegacyRandomAccessSpecialized&) const = default; // nvbug3908399 +#else + __host__ __device__ friend bool operator==(const LegacyRandomAccessSpecialized&, const LegacyRandomAccessSpecialized&) noexcept { return true;} + __host__ __device__ friend bool operator!=(const LegacyRandomAccessSpecialized&, const LegacyRandomAccessSpecialized&) noexcept { return true;} + __host__ __device__ friend bool operator<(const LegacyRandomAccessSpecialized&, const LegacyRandomAccessSpecialized&) noexcept { return true;} + __host__ __device__ friend bool operator<=(const LegacyRandomAccessSpecialized&, const LegacyRandomAccessSpecialized&) noexcept { return true;} + __host__ __device__ friend bool operator>(const LegacyRandomAccessSpecialized&, const LegacyRandomAccessSpecialized&) noexcept { return true;} + __host__ __device__ friend bool operator>=(const LegacyRandomAccessSpecialized&, const LegacyRandomAccessSpecialized&) noexcept { return true;} +#endif + + __host__ __device__ not_value_type& operator*() const; + __host__ __device__ not_value_type& operator[](long) const; + __host__ __device__ LegacyRandomAccessSpecialized& operator++(); + __host__ __device__ LegacyRandomAccessSpecialized operator++(int); + __host__ __device__ LegacyRandomAccessSpecialized& operator--(); + __host__ __device__ LegacyRandomAccessSpecialized operator--(int); + __host__ __device__ LegacyRandomAccessSpecialized& operator+=(long); + __host__ __device__ LegacyRandomAccessSpecialized& operator-=(long); + __host__ __device__ friend long operator-(LegacyRandomAccessSpecialized, LegacyRandomAccessSpecialized); + __host__ __device__ friend LegacyRandomAccessSpecialized operator-(LegacyRandomAccessSpecialized, int); + __host__ __device__ friend LegacyRandomAccessSpecialized operator+(LegacyRandomAccessSpecialized, int); + __host__ __device__ friend LegacyRandomAccessSpecialized operator+(int, LegacyRandomAccessSpecialized); +}; +template <> +struct cuda::std::iterator_traits +{ + using iterator_category = cuda::std::output_iterator_tag; + using value_type = short; + using difference_type = short; + using reference = short&; + using pointer = short*; +}; +using LegacyRandomAccessSpecializedTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +// Other test iterators. + +using InputTestIteratorTraits = cuda::std::iterator_traits>; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +#if 0 +using OutputTestIteratorTraits = cuda::std::iterator_traits>; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); +#endif + +using ForwardTestIteratorTraits = cuda::std::iterator_traits>; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +using BidirectionalTestIteratorTraits = cuda::std::iterator_traits>; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +using RandomAccessTestIteratorTraits = cuda::std::iterator_traits>; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +#ifdef _LIBCUDACXX_HAS_RANGES +using ContiguousTestIteratorTraits = cuda::std::iterator_traits>; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); +#endif + +using Cpp17BasicIteratorTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +using Cpp17InputIteratorTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +using Cpp17ForwardIteratorTraits = cuda::std::iterator_traits; +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(cuda::std::same_as); +static_assert(!has_iterator_concept_v); + +int main(int, char**) +{ + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/iterator.traits/iter_reference_t.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/iterator.traits/iter_reference_t.compile.pass.cpp new file mode 100644 index 00000000000..8cfe44aa23d --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/iterator.traits/iter_reference_t.compile.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// using iter_reference_t = decltype(*declval()); + +#include + +#include + +#include "test_iterators.h" + +static_assert(cuda::std::same_as >, int&>); +static_assert(cuda::std::same_as >, int&>); +static_assert(cuda::std::same_as >, int&>); +static_assert(cuda::std::same_as >, int&>); + +int main(int, char**) +{ + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/std.iterator.tags/contiguous_iterator_tag.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/std.iterator.tags/contiguous_iterator_tag.pass.cpp new file mode 100644 index 00000000000..5a55355664c --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.primitives/std.iterator.tags/contiguous_iterator_tag.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// struct contiguous_iterator_tag : public random_access_iterator_tag {}; + +// UNSUPPORTED: c++03, c++11, c++14 + + +#include +#include + +#include "test_macros.h" + +int main(int, char**) +{ + cuda::std::contiguous_iterator_tag tag; + ((void)tag); // Prevent unused warning + static_assert((cuda::std::is_base_of::value)); + static_assert((!cuda::std::is_base_of::value)); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/incrementable_traits.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/incrementable_traits.compile.pass.cpp new file mode 100644 index 00000000000..1f95783799f --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/incrementable_traits.compile.pass.cpp @@ -0,0 +1,271 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// struct incrementable_traits; + +#include + +#include + +#include "test_macros.h" + +#if TEST_STD_VER > 17 +template +concept check_has_difference_type = requires { + typename cuda::std::incrementable_traits::difference_type; +}; + +template +concept check_difference_type_matches = check_has_difference_type + && cuda::std::same_as::difference_type, Expected>; +#else +template +inline constexpr bool check_has_difference_type = false; + +template +inline constexpr bool + check_has_difference_type::difference_type>> = true; + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + check_difference_type_matches_, + requires()( + requires(check_has_difference_type), + requires(cuda::std::same_as::difference_type, Expected>) + )); + +template +_LIBCUDACXX_CONCEPT check_difference_type_matches = _LIBCUDACXX_FRAGMENT(check_difference_type_matches_, T, Expected); +#endif + + +template +__host__ __device__ constexpr bool check_incrementable_traits() { + constexpr bool result = check_difference_type_matches; + static_assert(check_difference_type_matches == result); + return result; +} + +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); + +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); + +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); + +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); + +static_assert(check_incrementable_traits()); +#ifdef INVESTIGATE_VOLATILE_POINTER +static_assert(check_incrementable_traits()); +#endif + +struct integral_difference_type { + using difference_type = int; +}; +static_assert(check_incrementable_traits()); + +struct non_integral_difference_type { + using difference_type = void; +}; +static_assert(check_incrementable_traits()); + +struct int_subtraction { + __host__ __device__ friend int operator-(int_subtraction, int_subtraction); +}; +static_assert(check_incrementable_traits()); +#ifdef INVESTIGATE_VOLATILE_REFERENCES +static_assert(!check_incrementable_traits()); +static_assert(!check_incrementable_traits()); +#endif + +struct char_subtraction { + __host__ __device__ friend char operator-(char_subtraction, char_subtraction); +}; +static_assert(check_incrementable_traits()); + +struct unsigned_int_subtraction_with_cv { + __host__ __device__ friend unsigned int operator-(unsigned_int_subtraction_with_cv const&, unsigned_int_subtraction_with_cv const&); + __host__ __device__ friend unsigned int operator-(unsigned_int_subtraction_with_cv const volatile&, unsigned_int_subtraction_with_cv const volatile&); +}; +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); +static_assert(check_incrementable_traits()); + +struct specialised_incrementable_traits {}; +template <> +struct cuda::std::incrementable_traits { + using difference_type = int; +}; +static_assert(check_incrementable_traits()); + +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); + +#if !defined(TEST_COMPILER_GCC) || __GNUC__ > 11 || TEST_STD_VER < 20 // gcc 10 has an issue with void +static_assert(!check_has_difference_type); +#endif // !defined(TEST_COMPILER_GCC) || __GNUC__ > 11 || TEST_STD_VER < 20 +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); +static_assert(!check_has_difference_type); + +#define TEST_POINTER_TO_MEMBER_FUNCTION(type, cv) \ + static_assert(!check_has_difference_type); \ + static_assert(!check_has_difference_type); \ + static_assert(!check_has_difference_type); \ + static_assert(!check_has_difference_type); \ + static_assert(!check_has_difference_type); \ + static_assert(!check_has_difference_type); + +struct empty {}; + +#define NO_QUALIFIER +TEST_POINTER_TO_MEMBER_FUNCTION(empty, NO_QUALIFIER); +TEST_POINTER_TO_MEMBER_FUNCTION(empty, const); +TEST_POINTER_TO_MEMBER_FUNCTION(empty, volatile); +TEST_POINTER_TO_MEMBER_FUNCTION(empty, const volatile); + +struct void_subtraction { + __host__ __device__ friend void operator-(void_subtraction, void_subtraction); +}; +static_assert(!check_has_difference_type); + +#define TEST_NOT_DIFFERENCE_TYPE(S, qual1, qual2) \ + struct S { \ + __host__ __device__ \ + friend int operator-(S qual1, S qual2); \ + }; \ + static_assert(!check_has_difference_type, "") + +TEST_NOT_DIFFERENCE_TYPE(A01, &, &); +TEST_NOT_DIFFERENCE_TYPE(A02, &, const&); +TEST_NOT_DIFFERENCE_TYPE(A03, &, volatile&); +TEST_NOT_DIFFERENCE_TYPE(A04, &, const volatile&); +TEST_NOT_DIFFERENCE_TYPE(A05, &, &&); +TEST_NOT_DIFFERENCE_TYPE(A06, &, const&&); +TEST_NOT_DIFFERENCE_TYPE(A07, &, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A08, &, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A11, const&, &); +// TEST_NOT_DIFFERENCE_TYPE(A12, const&, const&); // == true +TEST_NOT_DIFFERENCE_TYPE(A13, const&, volatile&); +// TEST_NOT_DIFFERENCE_TYPE(A14, const&, const volatile&); // invalid +TEST_NOT_DIFFERENCE_TYPE(A15, const&, &&); +TEST_NOT_DIFFERENCE_TYPE(A16, const&, const&&); +TEST_NOT_DIFFERENCE_TYPE(A17, const&, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A18, const&, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A21, volatile&, &); +TEST_NOT_DIFFERENCE_TYPE(A22, volatile&, const&); +TEST_NOT_DIFFERENCE_TYPE(A23, volatile&, volatile&); +TEST_NOT_DIFFERENCE_TYPE(A24, volatile&, const volatile&); +TEST_NOT_DIFFERENCE_TYPE(A25, volatile&, &&); +TEST_NOT_DIFFERENCE_TYPE(A26, volatile&, const&&); +TEST_NOT_DIFFERENCE_TYPE(A27, volatile&, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A28, volatile&, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A31, const volatile&, &); +// TEST_NOT_DIFFERENCE_TYPE(A32, const volatile&, const&); // invalid +TEST_NOT_DIFFERENCE_TYPE(A33, const volatile&, volatile&); +// TEST_NOT_DIFFERENCE_TYPE(A34, const volatile&, const volatile&); // invalid +TEST_NOT_DIFFERENCE_TYPE(A35, const volatile&, &&); +TEST_NOT_DIFFERENCE_TYPE(A36, const volatile&, const&&); +TEST_NOT_DIFFERENCE_TYPE(A37, const volatile&, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A38, const volatile&, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A41, &&, &); +TEST_NOT_DIFFERENCE_TYPE(A42, &&, const&); +TEST_NOT_DIFFERENCE_TYPE(A43, &&, volatile&); +TEST_NOT_DIFFERENCE_TYPE(A44, &&, const volatile&); +TEST_NOT_DIFFERENCE_TYPE(A45, &&, &&); +TEST_NOT_DIFFERENCE_TYPE(A46, &&, const&&); +TEST_NOT_DIFFERENCE_TYPE(A47, &&, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A48, &&, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A51, const&&, &); +TEST_NOT_DIFFERENCE_TYPE(A52, const&&, const&); +TEST_NOT_DIFFERENCE_TYPE(A53, const&&, volatile&); +TEST_NOT_DIFFERENCE_TYPE(A54, const&&, const volatile&); +TEST_NOT_DIFFERENCE_TYPE(A55, const&&, &&); +TEST_NOT_DIFFERENCE_TYPE(A56, const&&, const&&); +TEST_NOT_DIFFERENCE_TYPE(A57, const&&, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A58, const&&, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A61, volatile&&, &); +TEST_NOT_DIFFERENCE_TYPE(A62, volatile&&, const&); +TEST_NOT_DIFFERENCE_TYPE(A63, volatile&&, volatile&); +TEST_NOT_DIFFERENCE_TYPE(A64, volatile&&, const volatile&); +TEST_NOT_DIFFERENCE_TYPE(A65, volatile&&, &&); +TEST_NOT_DIFFERENCE_TYPE(A66, volatile&&, const&&); +TEST_NOT_DIFFERENCE_TYPE(A67, volatile&&, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A68, volatile&&, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A71, const volatile&&, &); +TEST_NOT_DIFFERENCE_TYPE(A72, const volatile&&, const&); +TEST_NOT_DIFFERENCE_TYPE(A73, const volatile&&, volatile&); +TEST_NOT_DIFFERENCE_TYPE(A74, const volatile&&, const volatile&); +TEST_NOT_DIFFERENCE_TYPE(A75, const volatile&&, &&); +TEST_NOT_DIFFERENCE_TYPE(A76, const volatile&&, const&&); +TEST_NOT_DIFFERENCE_TYPE(A77, const volatile&&, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A78, const volatile&&, const volatile&&); + +TEST_NOT_DIFFERENCE_TYPE(A81, &, NO_QUALIFIER); +// TEST_NOT_DIFFERENCE_TYPE(A82, const&, NO_QUALIFIER); // == true +TEST_NOT_DIFFERENCE_TYPE(A83, volatile&, NO_QUALIFIER); +// TEST_NOT_DIFFERENCE_TYPE(A84, const volatile&, NO_QUALIFIER); // invalid +TEST_NOT_DIFFERENCE_TYPE(A85, &&, NO_QUALIFIER); +TEST_NOT_DIFFERENCE_TYPE(A86, const&&, NO_QUALIFIER); +TEST_NOT_DIFFERENCE_TYPE(A87, volatile&&, NO_QUALIFIER); +TEST_NOT_DIFFERENCE_TYPE(A88, const volatile&&, NO_QUALIFIER); + +TEST_NOT_DIFFERENCE_TYPE(A91, NO_QUALIFIER, &); +// TEST_NOT_DIFFERENCE_TYPE(A92, NO_QUALIFIER, const&); // == true +TEST_NOT_DIFFERENCE_TYPE(A93, NO_QUALIFIER, volatile&); +// TEST_NOT_DIFFERENCE_TYPE(A94, NO_QUALIFIER, const volatile&); // invalid +TEST_NOT_DIFFERENCE_TYPE(A95, NO_QUALIFIER, &&); +TEST_NOT_DIFFERENCE_TYPE(A96, NO_QUALIFIER, const&&); +TEST_NOT_DIFFERENCE_TYPE(A97, NO_QUALIFIER, volatile&&); +TEST_NOT_DIFFERENCE_TYPE(A98, NO_QUALIFIER, const volatile&&); + +int main(int, char**) +{ + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_difference_t.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_difference_t.compile.pass.cpp new file mode 100644 index 00000000000..6a6a2afc199 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/incrementable.traits/iter_difference_t.compile.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// using iter_difference_t; + +#include + +#include + +#if TEST_STD_VER > 17 +template +inline constexpr bool has_no_iter_difference_t = !requires { typename cuda::std::iter_difference_t; }; + +#else +template +inline constexpr bool has_no_iter_difference_t = true; + +template +inline constexpr bool + has_no_iter_difference_t>> = false; +#endif + +template +__host__ __device__ constexpr bool check_iter_difference_t() { + constexpr bool result = cuda::std::same_as, Expected>; + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + + return result; +} + +static_assert(check_iter_difference_t()); +static_assert(check_iter_difference_t()); + +struct int_subtraction { + __host__ __device__ friend int operator-(int_subtraction, int_subtraction); +}; +static_assert(check_iter_difference_t()); + +static_assert(has_no_iter_difference_t); +static_assert(has_no_iter_difference_t); + +struct S {}; +static_assert(has_no_iter_difference_t); + +struct void_subtraction { + __host__ __device__ friend void operator-(void_subtraction, void_subtraction); +}; +static_assert(has_no_iter_difference_t); + +int main(int, char**) +{ + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/indirectly_readable_traits.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/indirectly_readable_traits.compile.pass.cpp new file mode 100644 index 00000000000..34ffc5a93b1 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/indirectly_readable_traits.compile.pass.cpp @@ -0,0 +1,168 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// struct indirectly_readable_traits; + +#include + +#include + +#if TEST_STD_VER > 17 +template +concept has_no_value_type = !requires { + typename cuda::std::indirectly_readable_traits::value_type; +}; + +template +concept value_type_matches = + cuda::std::same_as::value_type, Expected>; + +#else +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + has_no_value_type_, + requires() // + (typename(typename cuda::std::indirectly_readable_traits::value_type))); + +template +_LIBCUDACXX_CONCEPT has_no_value_type = !_LIBCUDACXX_FRAGMENT(has_no_value_type_, T); + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + value_type_matches_, + requires()( + typename(typename cuda::std::indirectly_readable_traits::value_type), + requires(cuda::std::same_as::value_type, Expected>) + )); + +template +_LIBCUDACXX_CONCEPT value_type_matches = _LIBCUDACXX_FRAGMENT(value_type_matches_, T, Expected); +#endif + +template +__host__ __device__ constexpr bool check_pointer() { + constexpr bool result = value_type_matches; + static_assert(value_type_matches == result); + static_assert(value_type_matches == result); + static_assert(value_type_matches == result); + + static_assert(value_type_matches == result); + static_assert(value_type_matches == result); + static_assert(value_type_matches == result); + static_assert(value_type_matches == result); + + return result; +} + +template +__host__ __device__ constexpr bool check_array() { + static_assert(value_type_matches); + static_assert(value_type_matches); + static_assert(value_type_matches); + static_assert(value_type_matches); + static_assert(value_type_matches); + static_assert(value_type_matches); + static_assert(value_type_matches); + static_assert(value_type_matches); + return true; +} + +template +__host__ __device__ constexpr bool check_member() { + static_assert(value_type_matches); + static_assert(value_type_matches); + static_assert(value_type_matches); + return true; +} + +static_assert(check_pointer()); +static_assert(check_pointer()); +static_assert(check_pointer()); +static_assert(!check_pointer()); +static_assert(!check_pointer()); + +static_assert(check_array()); +static_assert(check_array()); +static_assert(check_array()); + +template +struct ValueOf { + using value_type = T; +}; + +template +struct ElementOf { + using element_type = U; +}; + +template +struct TwoTypes { + using value_type = T; + using element_type = U; +}; + +static_assert(check_member, int>()); +static_assert(check_member, int[10]>()); +static_assert(check_member, int[]>()); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); + +static_assert(check_member, int>()); +static_assert(check_member, int[10]>()); +static_assert(check_member, int[]>()); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); + +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(check_member, int>()); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); +static_assert(has_no_value_type>); + +struct S2 {}; +template <> +struct cuda::std::indirectly_readable_traits { + using value_type = int; +}; +static_assert(value_type_matches); +static_assert(value_type_matches); +static_assert(has_no_value_type); +static_assert(has_no_value_type); +static_assert(has_no_value_type); +static_assert(has_no_value_type); + +static_assert(has_no_value_type); +static_assert(has_no_value_type); +static_assert(has_no_value_type); + +int main(int, char**) +{ + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp new file mode 100644 index 00000000000..2c32fd356a7 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// using iter_value_t; + +#include + +#include + +template +__host__ __device__ constexpr bool check_iter_value_t() { + constexpr bool result = cuda::std::same_as, Expected>; + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + static_assert(cuda::std::same_as, Expected> == result); + + return result; +} + +static_assert(check_iter_value_t()); +static_assert(check_iter_value_t()); +static_assert(check_iter_value_t()); + +struct both_members { + using value_type = double; + using element_type = double; +}; +static_assert(check_iter_value_t()); + +// clang-format off +template +inline constexpr bool check_no_iter_value_t = true; + +template +inline constexpr bool check_no_iter_value_t>> = false; + +static_assert(check_no_iter_value_t); +static_assert(check_no_iter_value_t); + +struct S {}; +static_assert(check_no_iter_value_t); + +struct different_value_element_members { + using value_type = int; + using element_type = long; +}; +static_assert(check_no_iter_value_t); + +int main(int, char**) { return 0; } diff --git a/libcudacxx/.upstream-tests/test/support/iterator_traits_cpp17_iterators.h b/libcudacxx/.upstream-tests/test/support/iterator_traits_cpp17_iterators.h new file mode 100644 index 00000000000..77557ee32ba --- /dev/null +++ b/libcudacxx/.upstream-tests/test/support/iterator_traits_cpp17_iterators.h @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// 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 TEST_SUPPORT_ITERATOR_TRAITS_ITERATOR_TRAITS_CPP17_ITERATORS +#define TEST_SUPPORT_ITERATOR_TRAITS_ITERATOR_TRAITS_CPP17_ITERATORS + +struct iterator_traits_cpp17_iterator { + __host__ __device__ int& operator*(); + __host__ __device__ iterator_traits_cpp17_iterator& operator++(); + __host__ __device__ iterator_traits_cpp17_iterator operator++(int); +}; + +struct iterator_traits_cpp17_proxy_iterator { + __host__ __device__ int operator*(); + __host__ __device__ iterator_traits_cpp17_proxy_iterator& operator++(); + + // this returns legcay_iterator, not iterator_traits_cpp17_proxy_iterator + __host__ __device__ iterator_traits_cpp17_iterator operator++(int); +}; + +struct iterator_traits_cpp17_input_iterator { + using difference_type = int; + using value_type = long; + + __host__ __device__ int& operator*(); + __host__ __device__ iterator_traits_cpp17_input_iterator& operator++(); + __host__ __device__ iterator_traits_cpp17_input_iterator operator++(int); + + __host__ __device__ bool operator==(iterator_traits_cpp17_input_iterator const&) const; +#if TEST_STD_VER < 20 + __host__ __device__ bool operator!=(iterator_traits_cpp17_input_iterator const&) const; +#endif +}; + +struct iterator_traits_cpp17_proxy_input_iterator { + using difference_type = int; + using value_type = long; + + __host__ __device__ int operator*(); + __host__ __device__ iterator_traits_cpp17_proxy_input_iterator& operator++(); + + // this returns legcay_input_iterator, not iterator_traits_cpp17_proxy_input_iterator + __host__ __device__ iterator_traits_cpp17_input_iterator operator++(int); + + __host__ __device__ bool operator==(iterator_traits_cpp17_proxy_input_iterator const&) const; +#if TEST_STD_VER < 20 + __host__ __device__ bool operator!=(iterator_traits_cpp17_proxy_input_iterator const&) const; +#endif +}; + +struct iterator_traits_cpp17_forward_iterator { + using difference_type = int; + using value_type = int; + + __host__ __device__ int& operator*(); + __host__ __device__ iterator_traits_cpp17_forward_iterator& operator++(); + __host__ __device__ iterator_traits_cpp17_forward_iterator operator++(int); + + __host__ __device__ bool operator==(iterator_traits_cpp17_forward_iterator const&) const; +#if TEST_STD_VER < 20 + __host__ __device__ bool operator!=(iterator_traits_cpp17_forward_iterator const&) const; +#endif +}; + +struct iterator_traits_cpp17_bidirectional_iterator { + using difference_type = int; + using value_type = int; + + __host__ __device__ int& operator*(); + __host__ __device__ iterator_traits_cpp17_bidirectional_iterator& operator++(); + __host__ __device__ iterator_traits_cpp17_bidirectional_iterator operator++(int); + __host__ __device__ iterator_traits_cpp17_bidirectional_iterator& operator--(); + __host__ __device__ iterator_traits_cpp17_bidirectional_iterator operator--(int); + + __host__ __device__ bool operator==(iterator_traits_cpp17_bidirectional_iterator const&) const; +#if TEST_STD_VER < 20 + __host__ __device__ bool operator!=(iterator_traits_cpp17_bidirectional_iterator const&) const; +#endif +}; + +struct iterator_traits_cpp17_random_access_iterator { + using difference_type = int; + using value_type = int; + + __host__ __device__ int& operator*(); + __host__ __device__ int& operator[](difference_type); + __host__ __device__ iterator_traits_cpp17_random_access_iterator& operator++(); + __host__ __device__ iterator_traits_cpp17_random_access_iterator operator++(int); + __host__ __device__ iterator_traits_cpp17_random_access_iterator& operator--(); + __host__ __device__ iterator_traits_cpp17_random_access_iterator operator--(int); + + __host__ __device__ bool operator==(iterator_traits_cpp17_random_access_iterator const&) const; +#if TEST_STD_VER < 20 + __host__ __device__ bool operator!=(iterator_traits_cpp17_random_access_iterator const&) const; +#endif + __host__ __device__ bool operator<(iterator_traits_cpp17_random_access_iterator const&) const; + __host__ __device__ bool operator>(iterator_traits_cpp17_random_access_iterator const&) const; + __host__ __device__ bool operator<=(iterator_traits_cpp17_random_access_iterator const&) const; + __host__ __device__ bool operator>=(iterator_traits_cpp17_random_access_iterator const&) const; + + __host__ __device__ iterator_traits_cpp17_random_access_iterator& operator+=(difference_type); + __host__ __device__ iterator_traits_cpp17_random_access_iterator& operator-=(difference_type); + + __host__ __device__ friend iterator_traits_cpp17_random_access_iterator operator+(iterator_traits_cpp17_random_access_iterator, + difference_type); + __host__ __device__ friend iterator_traits_cpp17_random_access_iterator operator+(difference_type, + iterator_traits_cpp17_random_access_iterator); + __host__ __device__ friend iterator_traits_cpp17_random_access_iterator operator-(iterator_traits_cpp17_random_access_iterator, + difference_type); + __host__ __device__ friend difference_type operator-(iterator_traits_cpp17_random_access_iterator, + iterator_traits_cpp17_random_access_iterator); +}; + +#endif // TEST_SUPPORT_ITERATOR_TRAITS_ITERATOR_TRAITS_CPP17_ITERATORS diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt b/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt index bbeaefc7ed2..3a9a89e2dec 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt @@ -90,6 +90,7 @@ set(files __iterator/erase_if_container.h __iterator/front_insert_iterator.h __iterator/insert_iterator.h + __iterator/incrementable_traits.h __iterator/istream_iterator.h __iterator/istreambuf_iterator.h __iterator/iterator.h @@ -99,6 +100,7 @@ set(files __iterator/ostream_iterator.h __iterator/ostreambuf_iterator.h __iterator/prev.h + __iterator/readable_traits.h __iterator/reverse_access.h __iterator/reverse_iterator.h __iterator/size.h diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/__concepts/constructible.h b/libcudacxx/include/cuda/std/detail/libcxx/include/__concepts/constructible.h index f60ea9d8456..a0f33cb27d0 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/__concepts/constructible.h +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/__concepts/constructible.h @@ -17,6 +17,7 @@ #include "../__concepts/__concept_macros.h" #include "../__concepts/convertible_to.h" #include "../__concepts/destructible.h" +#include "../__type_traits/add_lvalue_reference.h" #include "../__type_traits/is_constructible.h" #if defined(_LIBCUDACXX_USE_PRAGMA_GCC_SYSTEM_HEADER) diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/incrementable_traits.h b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/incrementable_traits.h new file mode 100644 index 00000000000..441d9326f90 --- /dev/null +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/incrementable_traits.h @@ -0,0 +1,136 @@ +// -*- 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_INCREMENTABLE_TRAITS_H +#define _LIBCUDACXX___ITERATOR_INCREMENTABLE_TRAITS_H + +#ifndef __cuda_std__ +#include <__config> +#endif // __cuda_std__ + +#include "../__concepts/arithmetic.h" +#include "../__type_traits/conditional.h" +#include "../__type_traits/enable_if.h" +#include "../__type_traits/is_const.h" +#include "../__type_traits/is_pointer.h" +#include "../__type_traits/is_primary_template.h" +#include "../__type_traits/make_signed.h" +#include "../__type_traits/remove_cvref.h" +#include "../__type_traits/void_t.h" +#include "../__utility/declval.h" +#include "../cstddef" + +#if defined(_LIBCUDACXX_USE_PRAGMA_GCC_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCUDACXX_BEGIN_NAMESPACE_STD + +#if _LIBCUDACXX_STD_VER > 17 + +// [incrementable.traits] +template struct incrementable_traits {}; + +template +requires is_object_v<_Tp> +struct incrementable_traits<_Tp*> { + using difference_type = ptrdiff_t; +}; + +template +struct incrementable_traits : incrementable_traits<_Ip> {}; + +template +concept __has_member_difference_type = requires { typename _Tp::difference_type; }; + +template<__has_member_difference_type _Tp> +struct incrementable_traits<_Tp> { + using difference_type = typename _Tp::difference_type; +}; + +template +concept __has_integral_minus = + requires(const _Tp& __x, const _Tp& __y) { + { __x - __y } -> integral; + }; + +template<__has_integral_minus _Tp> +requires (!__has_member_difference_type<_Tp>) +struct incrementable_traits<_Tp> { + using difference_type = make_signed_t() - declval<_Tp>())>; +}; + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; + +// Let `RI` be `remove_cvref_t`. The type `iter_difference_t` denotes +// `incrementable_traits::difference_type` if `iterator_traits` names a specialization +// generated from the primary template, and `iterator_traits::difference_type` otherwise. +template +using iter_difference_t = typename conditional_t<__is_primary_template>>::value, + incrementable_traits >, + iterator_traits > >::difference_type; + +#elif _LIBCUDACXX_STD_VER > 14 + +// [incrementable.traits] +template struct incrementable_traits {}; + +template +struct incrementable_traits<_Tp*, enable_if_t<_LIBCUDACXX_TRAIT(is_object, _Tp)>> { + using difference_type = ptrdiff_t; +}; + +template +struct incrementable_traits : incrementable_traits<_Ip> {}; + +template +inline constexpr bool __has_member_difference_type = false; + +template +inline constexpr bool __has_member_difference_type<_Tp, void_t> = true; + +template +inline constexpr bool __has_integral_minus = false; + +// In C++17 we get issues trying to bind void* to a const& so special case it here +template +inline constexpr bool __has_integral_minus<_Tp, enable_if_t>, + void_t() - _CUDA_VSTD::declval())>> + = integral() - _CUDA_VSTD::declval())>; + +template +struct incrementable_traits<_Tp, enable_if_t>> { + using difference_type = typename _Tp::difference_type; +}; + +template +struct incrementable_traits<_Tp, enable_if_t && __has_integral_minus<_Tp>>> { + using difference_type = make_signed_t() - declval<_Tp>())>; +}; + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; + +// Let `RI` be `remove_cvref_t`. The type `iter_difference_t` denotes +// `incrementable_traits::difference_type` if `iterator_traits` names a specialization +// generated from the primary template, and `iterator_traits::difference_type` otherwise. +template +using iter_difference_t = typename conditional_t<__is_primary_template>>::value, + incrementable_traits >, + iterator_traits > >::difference_type; + +#endif // _LIBCUDACXX_STD_VER > 14 + +_LIBCUDACXX_END_NAMESPACE_STD + +#endif // _LIBCUDACXX___ITERATOR_INCREMENTABLE_TRAITS_H diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/iterator_traits.h b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/iterator_traits.h index 6ee00482174..5e2d3d932e8 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/iterator_traits.h +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/iterator_traits.h @@ -15,9 +15,19 @@ #include <__config> #endif // __cuda_std__ +#include "../__concepts/arithmetic.h" +#include "../__concepts/constructible.h" +#include "../__concepts/convertible_to.h" +#include "../__concepts/copyable.h" +#include "../__concepts/equality_comparable.h" +#include "../__concepts/same_as.h" +#include "../__concepts/totally_ordered.h" #include "../__fwd/pair.h" +#include "../__iterator/incrementable_traits.h" +#include "../__iterator/readable_traits.h" #include "../__type_traits/add_const.h" #include "../__type_traits/is_convertible.h" +#include "../__type_traits/is_primary_template.h" #include "../__type_traits/remove_cv.h" #include "../__type_traits/void_t.h" #include "../cstddef" @@ -28,44 +38,653 @@ _LIBCUDACXX_BEGIN_NAMESPACE_STD +#if _LIBCUDACXX_STD_VER > 17 + +template +using __with_reference = _Tp&; + +template +concept __can_reference = requires { + typename __with_reference<_Tp>; +}; + +template +concept __dereferenceable = requires(_Tp& __t) { + { *__t } -> __can_reference; // not required to be equality-preserving +}; + +// [iterator.traits] +template<__dereferenceable _Tp> +using iter_reference_t = decltype(*declval<_Tp&>()); + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; + +#elif _LIBCUDACXX_STD_VER > 14 + +template +using __with_reference = _Tp&; + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __can_reference_, + requires() // + (typename(__with_reference<_Tp>))); + +template +_LIBCUDACXX_CONCEPT __can_reference = _LIBCUDACXX_FRAGMENT(__can_reference_, _Tp); + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __dereferenceable_, + requires(_Tp& __t)( + requires(__can_reference) + )); + +template +_LIBCUDACXX_CONCEPT __dereferenceable = _LIBCUDACXX_FRAGMENT(__dereferenceable_, _Tp); + +// [iterator.traits] +template +using iter_reference_t = enable_if_t<__dereferenceable<_Tp>, decltype(*_CUDA_VSTD::declval<_Tp&>())>; + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; +#else +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; +#endif // _LIBCUDACXX_STD_VER > 11 + struct _LIBCUDACXX_TEMPLATE_VIS input_iterator_tag {}; struct _LIBCUDACXX_TEMPLATE_VIS output_iterator_tag {}; struct _LIBCUDACXX_TEMPLATE_VIS forward_iterator_tag : public input_iterator_tag {}; struct _LIBCUDACXX_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {}; struct _LIBCUDACXX_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {}; +#if _LIBCUDACXX_STD_VER > 11 +struct _LIBCUDACXX_TEMPLATE_VIS contiguous_iterator_tag : public random_access_iterator_tag {}; +#endif + +template +struct __iter_traits_cache { + using type = _If< + __is_primary_template>::value, + _Iter, + iterator_traits<_Iter> + >; +}; +template +using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type; + +struct __iter_concept_concept_test { + template + using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept; +}; +struct __iter_concept_category_test { + template + using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category; +}; +struct __iter_concept_random_fallback { + template + using _Apply = __enable_if_t< + __is_primary_template>::value, + random_access_iterator_tag + >; +}; + +template struct __test_iter_concept + : _IsValidExpansion<_Tester::template _Apply, _Iter>, + _Tester +{ +}; + +template +struct __iter_concept_cache { + using type = _Or< + __test_iter_concept<_Iter, __iter_concept_concept_test>, + __test_iter_concept<_Iter, __iter_concept_category_test>, + __test_iter_concept<_Iter, __iter_concept_random_fallback> + >; +}; + +template +using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; + template struct __has_iterator_typedefs { private: - struct __two {char __lx; char __lxx;}; template - _LIBCUDACXX_INLINE_VISIBILITY static __two __test(...); + _LIBCUDACXX_INLINE_VISIBILITY static false_type __test(...); template - _LIBCUDACXX_INLINE_VISIBILITY static char __test( - __void_t* = 0, - __void_t* = 0, - __void_t* = 0, - __void_t* = 0, - __void_t* = 0); + _LIBCUDACXX_INLINE_VISIBILITY static true_type __test(__void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr, + __void_t* = nullptr); public: - static const bool value = sizeof(__test<_Tp>(0,0,0,0,0)) == 1; + static const bool value = decltype(__test<_Tp>(0,0,0,0,0))::value; }; - template struct __has_iterator_category { private: - struct __two {char __lx; char __lxx;}; - template - _LIBCUDACXX_INLINE_VISIBILITY static __two __test(...); - template - _LIBCUDACXX_INLINE_VISIBILITY static char __test(typename _Up::iterator_category* = 0); + template _LIBCUDACXX_INLINE_VISIBILITY static false_type __test(...); + template _LIBCUDACXX_INLINE_VISIBILITY static true_type __test(typename _Up::iterator_category* = nullptr); public: - static const bool value = sizeof(__test<_Tp>(0)) == 1; + static const bool value = decltype(__test<_Tp>(nullptr))::value; +}; + +template +struct __has_iterator_concept +{ +private: + template _LIBCUDACXX_INLINE_VISIBILITY static false_type __test(...); + template _LIBCUDACXX_INLINE_VISIBILITY static true_type __test(typename _Up::iterator_concept* = nullptr); +public: + static const bool value = decltype(__test<_Tp>(nullptr))::value; +}; + +#if _LIBCUDACXX_STD_VER > 17 + +// The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements +// from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to +// a "detail" namespace indicating they have a niche use-case. +namespace __iterator_traits_detail { +template +concept __cpp17_iterator = + requires(_Ip __i) { + { *__i } -> __can_reference; + { ++__i } -> same_as<_Ip&>; + { *__i++ } -> __can_reference; + } && + copyable<_Ip>; + +template +concept __cpp17_input_iterator = + __cpp17_iterator<_Ip> && + equality_comparable<_Ip> && + requires(_Ip __i) { + typename incrementable_traits<_Ip>::difference_type; + typename indirectly_readable_traits<_Ip>::value_type; + typename common_reference_t&&, + typename indirectly_readable_traits<_Ip>::value_type&>; + typename common_reference_t::value_type&>; + requires signed_integral::difference_type>; + }; + +template +concept __cpp17_forward_iterator = + __cpp17_input_iterator<_Ip> && + constructible_from<_Ip> && + is_lvalue_reference_v> && + same_as>, + typename indirectly_readable_traits<_Ip>::value_type> && + requires(_Ip __i) { + { __i++ } -> convertible_to<_Ip const&>; + { *__i++ } -> same_as>; + }; + +template +concept __cpp17_bidirectional_iterator = + __cpp17_forward_iterator<_Ip> && + requires(_Ip __i) { + { --__i } -> same_as<_Ip&>; + { __i-- } -> convertible_to<_Ip const&>; + { *__i-- } -> same_as>; + }; + +template +concept __cpp17_random_access_iterator = + __cpp17_bidirectional_iterator<_Ip> && + totally_ordered<_Ip> && + requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) { + { __i += __n } -> same_as<_Ip&>; + { __i -= __n } -> same_as<_Ip&>; + { __i + __n } -> same_as<_Ip>; + { __n + __i } -> same_as<_Ip>; + { __i - __n } -> same_as<_Ip>; + { __i - __i } -> same_as; // NOLINT(misc-redundant-expression) ; This is llvm.org/PR54114 + { __i[__n] } -> convertible_to>; + }; +} // namespace __iterator_traits_detail + +template +concept __has_member_reference = requires { typename _Ip::reference; }; + +template +concept __has_member_pointer = requires { typename _Ip::pointer; }; + +template +concept __has_member_iterator_category = requires { typename _Ip::iterator_category; }; + +template +concept __specifies_members = requires { + typename _Ip::value_type; + typename _Ip::difference_type; + requires __has_member_reference<_Ip>; + requires __has_member_iterator_category<_Ip>; + }; + +template +struct __iterator_traits_member_pointer_or_void { + using type = void; +}; + +template<__has_member_pointer _Tp> +struct __iterator_traits_member_pointer_or_void<_Tp> { + using type = typename _Tp::pointer; +}; + +template +concept __cpp17_iterator_missing_members = + !__specifies_members<_Tp> && + __iterator_traits_detail::__cpp17_iterator<_Tp>; + +template +concept __cpp17_input_iterator_missing_members = + __cpp17_iterator_missing_members<_Tp> && + __iterator_traits_detail::__cpp17_input_iterator<_Tp>; + +// Otherwise, `pointer` names `void`. +template +struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; }; + +// [iterator.traits]/3.2.1 +// If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type. +template<__has_member_pointer _Ip> +struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typename _Ip::pointer; }; + +// Otherwise, if `decltype(declval().operator->())` is well-formed, then `pointer` names that +// type. +template + requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>) +struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { + using type = decltype(declval<_Ip&>().operator->()); +}; + +// Otherwise, `reference` names `iter-reference-t`. +template +struct __iterator_traits_member_reference { using type = iter_reference_t<_Ip>; }; + +// [iterator.traits]/3.2.2 +// If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type. +template<__has_member_reference _Ip> +struct __iterator_traits_member_reference<_Ip> { using type = typename _Ip::reference; }; + +// [iterator.traits]/3.2.3.4 +// input_iterator_tag +template +struct __deduce_iterator_category { + using type = input_iterator_tag; +}; + +// [iterator.traits]/3.2.3.1 +// `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise +template<__iterator_traits_detail::__cpp17_random_access_iterator _Ip> +struct __deduce_iterator_category<_Ip> { + using type = random_access_iterator_tag; +}; + +// [iterator.traits]/3.2.3.2 +// `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise +template<__iterator_traits_detail::__cpp17_bidirectional_iterator _Ip> + requires (!__iterator_traits_detail::__cpp17_random_access_iterator<_Ip>) // nvbug 3885350 +struct __deduce_iterator_category<_Ip> { + using type = bidirectional_iterator_tag; +}; + +// [iterator.traits]/3.2.3.3 +// `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise +template<__iterator_traits_detail::__cpp17_forward_iterator _Ip> + requires (!__iterator_traits_detail::__cpp17_bidirectional_iterator<_Ip>) // nvbug 3885350 +struct __deduce_iterator_category<_Ip> { + using type = forward_iterator_tag; +}; + +template +struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {}; + +// [iterator.traits]/3.2.3 +// If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names +// that type. +template<__has_member_iterator_category _Ip> +struct __iterator_traits_iterator_category<_Ip> { + using type = typename _Ip::iterator_category; +}; + +// otherwise, it names void. +template +struct __iterator_traits_difference_type { using type = void; }; + +// If the qualified-id `incrementable_traits::difference_type` is valid and denotes a type, then +// `difference_type` names that type; +template +requires requires { typename incrementable_traits<_Ip>::difference_type; } +struct __iterator_traits_difference_type<_Ip> { + using type = typename incrementable_traits<_Ip>::difference_type; +}; + +// [iterator.traits]/3.4 +// Otherwise, `iterator_traits` has no members by any of the above names. +template +struct __iterator_traits {}; + +// [iterator.traits]/3.1 +// If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and +// `iterator-category`, then `iterator-traits` has the following publicly accessible members: +template<__specifies_members _Ip> +struct __iterator_traits<_Ip> { + using iterator_category = typename _Ip::iterator_category; + using value_type = typename _Ip::value_type; + using difference_type = typename _Ip::difference_type; + using pointer = typename __iterator_traits_member_pointer_or_void<_Ip>::type; + using reference = typename _Ip::reference; +}; + +// [iterator.traits]/3.2 +// Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`, +// `iterator-traits` has the following publicly accessible members: +template<__cpp17_input_iterator_missing_members _Ip> +struct __iterator_traits<_Ip> { + using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type; + using value_type = typename indirectly_readable_traits<_Ip>::value_type; + using difference_type = typename incrementable_traits<_Ip>::difference_type; + using pointer = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type; + using reference = typename __iterator_traits_member_reference<_Ip>::type; +}; + +// Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then +// `iterator_traits` has the following publicly accessible members: +template<__cpp17_iterator_missing_members _Ip> + requires (!__cpp17_input_iterator_missing_members<_Ip>) // nvbug 3885350 +struct __iterator_traits<_Ip> { + using iterator_category = output_iterator_tag; + using value_type = void; + using difference_type = typename __iterator_traits_difference_type<_Ip>::type; + using pointer = void; + using reference = void; +}; + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits : __iterator_traits<_Ip> { + using __primary_template = iterator_traits; }; +#elif _LIBCUDACXX_STD_VER > 14 + +// The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements +// from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to +// a "detail" namespace indicating they have a niche use-case. +namespace __iterator_traits_detail { +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __cpp17_iterator_, + requires(_Ip __i) // + (requires(__can_reference), + requires(same_as<_Ip&, decltype(++__i)>), + requires(__can_reference), + requires(copyable<_Ip>))); + +template +_LIBCUDACXX_CONCEPT __cpp17_iterator = _LIBCUDACXX_FRAGMENT(__cpp17_iterator_, _Ip); + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __cpp17_input_iterator_, + requires(_Ip __i)( + typename(common_reference_t&&, typename indirectly_readable_traits<_Ip>::value_type&>), + typename(common_reference_t::value_type&>), + requires(__cpp17_iterator<_Ip>), + requires(equality_comparable<_Ip>), + requires(__has_member_difference_type>), + requires(__has_member_value_type>), + requires(signed_integral::difference_type>) + )); + +template +_LIBCUDACXX_CONCEPT __cpp17_input_iterator = _LIBCUDACXX_FRAGMENT(__cpp17_input_iterator_, _Ip); + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __cpp17_forward_iterator_, + requires(_Ip __i)( + requires(__cpp17_input_iterator<_Ip>), + requires(convertible_to), + requires(same_as, decltype(*__i++)>), + requires(constructible_from<_Ip>), + requires(_LIBCUDACXX_TRAIT(is_lvalue_reference, iter_reference_t<_Ip>)), + requires(same_as>, typename indirectly_readable_traits<_Ip>::value_type>) + )); + +template +_LIBCUDACXX_CONCEPT __cpp17_forward_iterator = _LIBCUDACXX_FRAGMENT(__cpp17_forward_iterator_, _Ip); + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __cpp17_bidirectional_iterator_, + requires(_Ip __i)( + requires(__cpp17_forward_iterator<_Ip>), + requires(same_as<_Ip&, decltype(--__i)>), + requires(convertible_to), + requires(same_as, decltype(*__i--)>) + )); + +template +_LIBCUDACXX_CONCEPT __cpp17_bidirectional_iterator = _LIBCUDACXX_FRAGMENT(__cpp17_bidirectional_iterator_, _Ip); + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __cpp17_random_access_iterator_, + requires(_Ip __i, typename incrementable_traits<_Ip>::difference_type __n) // + (requires(same_as<_Ip&, decltype(__i += __n)>), + requires(same_as<_Ip&, decltype(__i -= __n)>), + requires(same_as<_Ip, decltype(__i + __n)>), + requires(same_as<_Ip, decltype(__n + __i)>), + requires(same_as<_Ip, decltype(__i - __n)>), + requires(same_as), + requires(convertible_to>))); + +template +_LIBCUDACXX_CONCEPT __cpp17_random_access_iterator = + __cpp17_bidirectional_iterator<_Ip> && + totally_ordered<_Ip> && + _LIBCUDACXX_FRAGMENT(__cpp17_random_access_iterator_, _Ip); +} // namespace __iterator_traits_detail + +template +inline constexpr bool __has_member_reference = false; + +template +inline constexpr bool __has_member_reference<_Tp, void_t> = true; + +template +inline constexpr bool __has_member_pointer = false; + +template +inline constexpr bool __has_member_pointer<_Tp, void_t> = true; + +template +inline constexpr bool __has_member_iterator_category = false; + +template +inline constexpr bool __has_member_iterator_category<_Tp, void_t> = true; + +template +_LIBCUDACXX_CONCEPT __specifies_members = + __has_member_value_type<_Ip> && + __has_member_difference_type<_Ip> && + __has_member_reference<_Ip> && + __has_member_iterator_category<_Ip>; + +template +struct __iterator_traits_member_pointer_or_void { + using type = void; +}; + +template +struct __iterator_traits_member_pointer_or_void<_Tp, enable_if_t<__has_member_pointer<_Tp>>> { + using type = typename _Tp::pointer; +}; + +template +_LIBCUDACXX_CONCEPT __cpp17_iterator_missing_members = + !__specifies_members<_Tp> && + __iterator_traits_detail::__cpp17_iterator<_Tp>; + +template +_LIBCUDACXX_CONCEPT __cpp17_input_iterator_missing_members = + __cpp17_iterator_missing_members<_Tp> && + __iterator_traits_detail::__cpp17_input_iterator<_Tp>; + +// Otherwise, `pointer` names `void`. +template +struct __iterator_traits_member_pointer_or_arrow_or_void { using type = void; }; + +// [iterator.traits]/3.2.1 +// If the qualified-id `I::pointer` is valid and denotes a type, `pointer` names that type. +template +struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip, enable_if_t<__has_member_pointer<_Ip>>> +{ using type = typename _Ip::pointer; }; + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __has_operator_arrow_, + requires(_Ip& __i) // + (__i.operator->())); + +template +_LIBCUDACXX_CONCEPT __has_operator_arrow = _LIBCUDACXX_FRAGMENT(__has_operator_arrow_, _Ip); + +// Otherwise, if `decltype(declval().operator->())` is well-formed, then `pointer` names that +// type. +template +struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip, + enable_if_t<__has_operator_arrow<_Ip> && !__has_member_pointer<_Ip>>> { + using type = decltype(declval<_Ip&>().operator->()); +}; + +// Otherwise, `reference` names `iter-reference-t`. +template +struct __iterator_traits_member_reference { using type = iter_reference_t<_Ip>; }; + +// [iterator.traits]/3.2.2 +// If the qualified-id `I::reference` is valid and denotes a type, `reference` names that type. +template +struct __iterator_traits_member_reference<_Ip, enable_if_t<__has_member_reference<_Ip>>> +{ using type = typename _Ip::reference; }; + +// [iterator.traits]/3.2.3.4 +// input_iterator_tag +template +struct __deduce_iterator_category { + using type = input_iterator_tag; +}; + +// [iterator.traits]/3.2.3.1 +// `random_access_iterator_tag` if `I` satisfies `cpp17-random-access-iterator`, or otherwise +template +struct __deduce_iterator_category<_Ip, enable_if_t< + __iterator_traits_detail::__cpp17_random_access_iterator<_Ip>>> { + using type = random_access_iterator_tag; +}; + +// [iterator.traits]/3.2.3.2 +// `bidirectional_iterator_tag` if `I` satisfies `cpp17-bidirectional-iterator`, or otherwise +template +struct __deduce_iterator_category<_Ip, enable_if_t< + !__iterator_traits_detail::__cpp17_random_access_iterator<_Ip> && + __iterator_traits_detail::__cpp17_bidirectional_iterator<_Ip>>> { + using type = bidirectional_iterator_tag; +}; + +// [iterator.traits]/3.2.3.3 +// `forward_iterator_tag` if `I` satisfies `cpp17-forward-iterator`, or otherwise +template +struct __deduce_iterator_category<_Ip, enable_if_t< + !__iterator_traits_detail::__cpp17_bidirectional_iterator<_Ip> && + __iterator_traits_detail::__cpp17_forward_iterator<_Ip>>> { + using type = forward_iterator_tag; +}; + +template +struct __iterator_traits_iterator_category : __deduce_iterator_category<_Ip> {}; + +// [iterator.traits]/3.2.3 +// If the qualified-id `I::iterator-category` is valid and denotes a type, `iterator-category` names +// that type. +template +struct __iterator_traits_iterator_category<_Ip, enable_if_t< + __has_member_iterator_category<_Ip>>> { + using type = typename _Ip::iterator_category; +}; + +// otherwise, it names void. +template +struct __iterator_traits_difference_type { using type = void; }; + +// If the qualified-id `incrementable_traits::difference_type` is valid and denotes a type, then +// `difference_type` names that type; +template +struct __iterator_traits_difference_type<_Ip, void_t< + typename incrementable_traits<_Ip>::difference_type>> { + using type = typename incrementable_traits<_Ip>::difference_type; +}; + +// [iterator.traits]/3.4 +// Otherwise, `iterator_traits` has no members by any of the above names. +template +struct __iterator_traits {}; + +// [iterator.traits]/3.1 +// If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and +// `iterator-category`, then `iterator-traits` has the following publicly accessible members: +template +struct __iterator_traits<_Ip, enable_if_t<__specifies_members<_Ip>>> { + using iterator_category = typename _Ip::iterator_category; + using value_type = typename _Ip::value_type; + using difference_type = typename _Ip::difference_type; + using pointer = typename __iterator_traits_member_pointer_or_void<_Ip>::type; + using reference = typename _Ip::reference; +}; + +// [iterator.traits]/3.2 +// Otherwise, if `I` satisfies the exposition-only concept `cpp17-input-iterator`, +// `iterator-traits` has the following publicly accessible members: +template +struct __iterator_traits<_Ip, enable_if_t && + __cpp17_input_iterator_missing_members<_Ip>>> { + using iterator_category = typename __iterator_traits_iterator_category<_Ip>::type; + using value_type = typename indirectly_readable_traits<_Ip>::value_type; + using difference_type = typename incrementable_traits<_Ip>::difference_type; + using pointer = typename __iterator_traits_member_pointer_or_arrow_or_void<_Ip>::type; + using reference = typename __iterator_traits_member_reference<_Ip>::type; +}; + +// Otherwise, if `I` satisfies the exposition-only concept `cpp17-iterator`, then +// `iterator_traits` has the following publicly accessible members: +template +struct __iterator_traits<_Ip, enable_if_t && + !__cpp17_input_iterator_missing_members<_Ip> && + __cpp17_iterator_missing_members<_Ip>>> { + using iterator_category = output_iterator_tag; + using value_type = void; + using difference_type = typename __iterator_traits_difference_type<_Ip>::type; + using pointer = void; + using reference = void; +}; + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits : __iterator_traits<_Ip> { + using __primary_template = iterator_traits; +}; + +#else // _LIBCUDACXX_STD_VER > 11 + +template struct __iterator_traits {}; + template struct __iterator_traits_impl {}; template @@ -78,8 +697,6 @@ struct __iterator_traits_impl<_Iter, true> typedef typename _Iter::iterator_category iterator_category; }; -template struct __iterator_traits {}; - template struct __iterator_traits<_Iter, true> : __iterator_traits_impl @@ -97,25 +714,43 @@ struct __iterator_traits<_Iter, true> template struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits - : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {}; + : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { + + using __primary_template = iterator_traits; +}; +#endif // _LIBCUDACXX_STD_VER < 17 template +#if _LIBCUDACXX_STD_VER > 17 +requires is_object_v<_Tp> +#endif struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits<_Tp*> { typedef ptrdiff_t difference_type; typedef __remove_cv_t<_Tp> value_type; typedef _Tp* pointer; - typedef _Tp& reference; + typedef typename add_lvalue_reference<_Tp>::type reference; typedef random_access_iterator_tag iterator_category; +#if _LIBCUDACXX_STD_VER > 14 + typedef contiguous_iterator_tag iterator_concept; +#endif }; template >::value> struct __has_iterator_category_convertible_to - : public integral_constant::iterator_category, _Up>::value> + : is_convertible::iterator_category, _Up> +{}; + +template +struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {}; + +template ::value> +struct __has_iterator_concept_convertible_to + : is_convertible {}; template -struct __has_iterator_category_convertible_to<_Tp, _Up, false> : public false_type {}; +struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; template struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {}; @@ -129,27 +764,75 @@ struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_conver template struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {}; +// __is_cpp17_contiguous_iterator determines if an iterator is known by +// libc++ to be contiguous, either because it advertises itself as such +// (in C++20) or because it is a pointer type or a known trivial wrapper +// around a (possibly fancy) pointer type, such as __wrap_iter. +// Such iterators receive special "contiguous" optimizations in +// std::copy and std::sort. +// +#if _LIBCUDACXX_STD_VER > 14 +template +struct __is_cpp17_contiguous_iterator : _Or< + __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>, + __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag> +> {}; +#else +template +struct __is_cpp17_contiguous_iterator : false_type {}; +#endif + +// Any native pointer which is an iterator is also a contiguous iterator. +template +struct __is_cpp17_contiguous_iterator<_Up*> : true_type {}; + + +template +class __wrap_iter; + template struct __is_exactly_cpp17_input_iterator : public integral_constant::value && !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; -#ifndef _LIBCUDACXX_HAS_NO_DEDUCTION_GUIDES +template +struct __is_exactly_cpp17_forward_iterator + : public integral_constant::value && + !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value> {}; + +template +struct __is_exactly_cpp17_bidirectional_iterator + : public integral_constant::value && + !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value> {}; + template using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; template -using __iter_key_type = remove_const_t::value_type::first_type>; +using __iter_key_type = typename remove_const::value_type::first_type>::type; template using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; template using __iter_to_alloc_type = pair< - add_const_t::value_type::first_type>, + typename add_const::value_type::first_type>::type, typename iterator_traits<_InputIterator>::value_type::second_type>; -#endif + +template +using __iterator_category_type = typename iterator_traits<_Iter>::iterator_category; + +template +using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; + +template +using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; + +template +using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; _LIBCUDACXX_END_NAMESPACE_STD diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/readable_traits.h b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/readable_traits.h new file mode 100644 index 00000000000..e8a74fc921d --- /dev/null +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/readable_traits.h @@ -0,0 +1,159 @@ +// -*- 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_READABLE_TRAITS_H +#define _LIBCUDACXX___ITERATOR_READABLE_TRAITS_H + +#ifndef __cuda_std__ +#include <__config> +#endif // __cuda_std__ + +#include "../__type_traits/is_primary_template.h" +#include "../__type_traits/conditional.h" +#include "../__type_traits/enable_if.h" +#include "../__type_traits/is_array.h" +#include "../__type_traits/is_const.h" +#include "../__type_traits/is_object.h" +#include "../__type_traits/is_primary_template.h" +#include "../__type_traits/remove_cv.h" +#include "../__type_traits/remove_cvref.h" +#include "../__type_traits/remove_extent.h" +#include "../__type_traits/void_t.h" + +#if defined(_LIBCUDACXX_USE_PRAGMA_GCC_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCUDACXX_BEGIN_NAMESPACE_STD + +#if _LIBCUDACXX_STD_VER > 17 + +// [readable.traits] +template struct __cond_value_type {}; + +template +requires is_object_v<_Tp> +struct __cond_value_type<_Tp> { using value_type = remove_cv_t<_Tp>; }; + +template +concept __has_member_value_type = requires { typename _Tp::value_type; }; + +template +concept __has_member_element_type = requires { typename _Tp::element_type; }; + +template struct indirectly_readable_traits {}; + +template +requires is_array_v<_Ip> +struct indirectly_readable_traits<_Ip> { + using value_type = remove_cv_t>; +}; + +template +struct indirectly_readable_traits : indirectly_readable_traits<_Ip> {}; + +template +struct indirectly_readable_traits<_Tp*> : __cond_value_type<_Tp> {}; + +template<__has_member_value_type _Tp> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +template<__has_member_element_type _Tp> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +template<__has_member_value_type _Tp> + requires __has_member_element_type<_Tp> +struct indirectly_readable_traits<_Tp> {}; + +template<__has_member_value_type _Tp> + requires __has_member_element_type<_Tp> && + same_as, + remove_cv_t> +struct indirectly_readable_traits<_Tp> + : __cond_value_type {}; + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; + +// Let `RI` be `remove_cvref_t`. The type `iter_value_t` denotes +// `indirectly_readable_traits::value_type` if `iterator_traits` names a specialization +// generated from the primary template, and `iterator_traits::value_type` otherwise. +template +using iter_value_t = typename conditional_t<__is_primary_template>>::value, + indirectly_readable_traits >, + iterator_traits > >::value_type; + +#elif _LIBCUDACXX_STD_VER > 14 + +// [readable.traits] +template struct __cond_value_type {}; + +template +struct __cond_value_type<_Tp, enable_if_t<_LIBCUDACXX_TRAIT(is_object, _Tp)>> { using value_type = remove_cv_t<_Tp>; }; + +template +inline constexpr bool __has_member_value_type = false; + +template +inline constexpr bool __has_member_value_type<_Tp, void_t> = true; + +template +inline constexpr bool __has_member_element_type = false; + +template +inline constexpr bool __has_member_element_type<_Tp, void_t> = true; + +template struct indirectly_readable_traits {}; + +template +struct indirectly_readable_traits<_Ip, enable_if_t> { + using value_type = remove_cv_t>; +}; + +template +struct indirectly_readable_traits + : indirectly_readable_traits<_Ip> {}; + +template +struct indirectly_readable_traits<_Tp*> + : __cond_value_type<_Tp> {}; + +template +struct indirectly_readable_traits<_Tp, enable_if_t && !__has_member_element_type<_Tp>>> + : __cond_value_type {}; + +template +struct indirectly_readable_traits<_Tp, enable_if_t && __has_member_element_type<_Tp>>> + : __cond_value_type {}; + +template +struct indirectly_readable_traits<_Tp, enable_if_t && __has_member_element_type<_Tp> && + same_as, + remove_cv_t>>> + : __cond_value_type {}; + +template +struct _LIBCUDACXX_TEMPLATE_VIS iterator_traits; + +// Let `RI` be `remove_cvref_t`. The type `iter_value_t` denotes +// `indirectly_readable_traits::value_type` if `iterator_traits` names a specialization +// generated from the primary template, and `iterator_traits::value_type` otherwise. +template +using iter_value_t = typename conditional_t<__is_primary_template>>::value, + indirectly_readable_traits >, + iterator_traits > >::value_type; + +#endif // _LIBCUDACXX_STD_VER > 14 + +_LIBCUDACXX_END_NAMESPACE_STD + +#endif // _LIBCUDACXX___ITERATOR_READABLE_TRAITS_H diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/iterator b/libcudacxx/include/cuda/std/detail/libcxx/include/iterator index abd756204bc..c4562b59452 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/iterator +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/iterator @@ -689,6 +689,7 @@ template constexpr const E* data(initializer_list il) noexcept; #include "__iterator/empty.h" #include "__iterator/erase_if_container.h" #include "__iterator/front_insert_iterator.h" +#include "__iterator/incrementable_traits.h" #include "__iterator/insert_iterator.h" #include "__iterator/istream_iterator.h" #include "__iterator/istreambuf_iterator.h" @@ -699,6 +700,7 @@ template constexpr const E* data(initializer_list il) noexcept; #include "__iterator/ostream_iterator.h" #include "__iterator/ostreambuf_iterator.h" #include "__iterator/prev.h" +#include "__iterator/readable_traits.h" #include "__iterator/reverse_access.h" #include "__iterator/reverse_iterator.h" #include "__iterator/size.h" diff --git a/libcudacxx/libcxx/test/std/containers/associative/map/map.cons/default_recursive.pass.cpp b/libcudacxx/libcxx/test/std/containers/associative/map/map.cons/default_recursive.pass.cpp index 610ca109ef5..d2702bc21da 100644 --- a/libcudacxx/libcxx/test/std/containers/associative/map/map.cons/default_recursive.pass.cpp +++ b/libcudacxx/libcxx/test/std/containers/associative/map/map.cons/default_recursive.pass.cpp @@ -21,8 +21,11 @@ struct X std::map m; std::map::iterator i; std::map::const_iterator ci; +#if TEST_STD_VER <= 14 + // These reverse_iterator specializations require X to be complete in C++20 (and C++17 because of backport of ranges). std::map::reverse_iterator ri; std::map::const_reverse_iterator cri; +#endif // TEST_STD_VER <= 14 }; int main(int, char**) diff --git a/libcudacxx/libcxx/test/std/containers/associative/multimap/multimap.cons/default_recursive.pass.cpp b/libcudacxx/libcxx/test/std/containers/associative/multimap/multimap.cons/default_recursive.pass.cpp index e468ebf023b..86b6f658f2f 100644 --- a/libcudacxx/libcxx/test/std/containers/associative/multimap/multimap.cons/default_recursive.pass.cpp +++ b/libcudacxx/libcxx/test/std/containers/associative/multimap/multimap.cons/default_recursive.pass.cpp @@ -21,12 +21,11 @@ struct X std::multimap m; std::multimap::iterator i; std::multimap::const_iterator ci; +#if TEST_STD_VER <= 14 + // These reverse_iterator specializations require X to be complete in C++20 (and C++17 because of backport of ranges). std::multimap::reverse_iterator ri; std::multimap::const_reverse_iterator cri; +#endif // TEST_STD_VER <= 14 }; -int main(int, char**) -{ - - return 0; -} +int main(int, char**) { return 0; } diff --git a/libcudacxx/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.fail.cpp b/libcudacxx/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.fail.cpp index f683ae93bea..21720d53c3b 100644 --- a/libcudacxx/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.fail.cpp +++ b/libcudacxx/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.fail.cpp @@ -91,7 +91,7 @@ int main(int, char**) typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std:{{.*}}:iterator_traits<{{.+}}>}} typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std:{{.*}}:iterator_traits<{{.+}}>}} } -#if TEST_STD_VER <= 17 || !defined(__cpp_lib_concepts) +#if TEST_STD_VER <= 14 || !defined(__cpp_lib_concepts) { typedef std::iterator_traits T; typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std:{{.*}}:iterator_traits<{{.+}}>}} @@ -100,7 +100,7 @@ int main(int, char**) typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std:{{.*}}:iterator_traits<{{.+}}>}} typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std:{{.*}}:iterator_traits<{{.+}}>}} } -#endif // TEST_STD_VER <= 17 || !defined(__cpp_lib_concepts) +#endif // TEST_STD_VER <= 14 || !defined(__cpp_lib_concepts) { typedef std::iterator_traits T; typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std:{{.*}}:iterator_traits<{{.+}}>}}