Skip to content

Commit

Permalink
Implement the indirectly_comparable concept
Browse files Browse the repository at this point in the history
  • Loading branch information
miscco committed Sep 20, 2023
1 parent f2866f6 commit 0bc6e43
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// 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<class I1, class I2, class R, class P1, class P2>
// concept indirectly_comparable;

#include <cuda/std/functional>
#include <cuda/std/iterator>
#include <cuda/std/type_traits>

struct Deref {
__host__ __device__ int operator()(int*) const;
};

static_assert(!cuda::std::indirectly_comparable<int, int, cuda::std::less<int>>); // not dereferenceable
static_assert(!cuda::std::indirectly_comparable<int*, int*, int>); // not a predicate
static_assert( cuda::std::indirectly_comparable<int*, int*, cuda::std::less<int>>);
static_assert(!cuda::std::indirectly_comparable<int**, int*, cuda::std::less<int>>);
static_assert( cuda::std::indirectly_comparable<int**, int*, cuda::std::less<int>, Deref>);
static_assert(!cuda::std::indirectly_comparable<int**, int*, cuda::std::less<int>, Deref, Deref>);
static_assert(!cuda::std::indirectly_comparable<int**, int*, cuda::std::less<int>, cuda::std::identity, Deref>);
static_assert( cuda::std::indirectly_comparable<int*, int**, cuda::std::less<int>, cuda::std::identity, Deref>);

int main(int, char**)
{
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===----------------------------------------------------------------------===//
//
// 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, c++17

// template<class I1, class I2, class R, class P1, class P2>
// concept indirectly_comparable;

#include <cuda/std/functional>
#include <cuda/std/iterator>
#include <cuda/std/type_traits>

template<class F>
requires cuda::std::indirectly_comparable<int*, char*, F>
&& true // This true is an additional atomic constraint as a tie breaker
__host__ __device__ constexpr bool subsumes(F) { return true; }

template<class F>
requires cuda::std::indirect_binary_predicate<F, cuda::std::projected<int*, cuda::std::identity>, cuda::std::projected<char*, cuda::std::identity>>
__host__ __device__ void subsumes(F);

template<class F>
requires cuda::std::indirect_binary_predicate<F, cuda::std::projected<int*, cuda::std::identity>, cuda::std::projected<char*, cuda::std::identity>>
&& true // This true is an additional atomic constraint as a tie breaker
__host__ __device__ constexpr bool is_subsumed(F) { return true; }

template<class F>
requires cuda::std::indirectly_comparable<int*, char*, F>
__host__ __device__ void is_subsumed(F);

static_assert(subsumes(cuda::std::less<int>()));
static_assert(is_subsumed(cuda::std::less<int>()));

int main(int, char**)
{
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ set(files
__iterator/front_insert_iterator.h
__iterator/insert_iterator.h
__iterator/incrementable_traits.h
__iterator/indirectly_comparable.h
__iterator/istream_iterator.h
__iterator/istreambuf_iterator.h
__iterator/iter_move.h
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// -*- 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_INDIRECTLY_COMPARABLE_H
#define _LIBCUDACXX___ITERATOR_INDIRECTLY_COMPARABLE_H

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

#include "../__functional/identity.h"
#include "../__iterator/concepts.h"
#include "../__iterator/projected.h"

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

_LIBCUDACXX_BEGIN_NAMESPACE_STD

#if _LIBCUDACXX_STD_VER > 17

template <class _Iter1, class _Iter2, class _BinaryPred,
class _Proj1 = identity, class _Proj2 = identity>
concept indirectly_comparable =
indirect_binary_predicate<_BinaryPred, projected<_Iter1, _Proj1>,
projected<_Iter2, _Proj2>>;

#elif _LIBCUDACXX_STD_VER > 14

// clang-format off

template <class _Iter1, class _Iter2, class _BinaryPred, class _Proj1, class _Proj2>
_LIBCUDACXX_CONCEPT_FRAGMENT(
__indirectly_comparable_,
requires()(
requires(indirect_binary_predicate<_BinaryPred, projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>>)
));

template <class _Iter1, class _Iter2, class _BinaryPred, class _Proj1 = identity, class _Proj2 = identity>
_LIBCUDACXX_CONCEPT indirectly_comparable =
_LIBCUDACXX_FRAGMENT(__indirectly_comparable_, _Iter1, _Iter2, _BinaryPred, _Proj1, _Proj2);

// clang-format on

#endif // _LIBCUDACXX_STD_VER > 14

_LIBCUDACXX_END_NAMESPACE_STD

#endif // _LIBCUDACXX___ITERATOR_INDIRECTLY_COMPARABLE_H
1 change: 1 addition & 0 deletions libcudacxx/include/cuda/std/detail/libcxx/include/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
#include "__iterator/erase_if_container.h"
#include "__iterator/front_insert_iterator.h"
#include "__iterator/incrementable_traits.h"
#include "__iterator/indirectly_comparable.h"
#include "__iterator/insert_iterator.h"
#include "__iterator/istream_iterator.h"
#include "__iterator/istreambuf_iterator.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

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

// template<class I1, class I2, class R, class P1, class P2>
// concept indirectly_comparable;

#include <functional>
#include <iterator>
#include <type_traits>

struct Deref {
int operator()(int*) const;
};

static_assert(!std::indirectly_comparable<int, int, std::less<int>>); // not dereferenceable
static_assert(!std::indirectly_comparable<int*, int*, int>); // not a predicate
static_assert( std::indirectly_comparable<int*, int*, std::less<int>>);
static_assert(!std::indirectly_comparable<int**, int*, std::less<int>>);
static_assert( std::indirectly_comparable<int**, int*, std::less<int>, Deref>);
static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, Deref, Deref>);
static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, std::identity, Deref>);
static_assert( std::indirectly_comparable<int*, int**, std::less<int>, std::identity, Deref>);

template<class F>
requires std::indirectly_comparable<int*, char*, F>
&& true // This true is an additional atomic constraint as a tie breaker
constexpr bool subsumes(F) { return true; }

template<class F>
requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>>
void subsumes(F);

template<class F>
requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>>
&& true // This true is an additional atomic constraint as a tie breaker
constexpr bool is_subsumed(F) { return true; }

template<class F>
requires std::indirectly_comparable<int*, char*, F>
void is_subsumed(F);

static_assert(subsumes(std::less<int>()));
static_assert(is_subsumed(std::less<int>()));

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

0 comments on commit 0bc6e43

Please sign in to comment.