Skip to content

Commit

Permalink
move is_contiguous_iterator to type_support, support array iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
isidorostsa committed Sep 11, 2023
1 parent 8531572 commit a43f622
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#pragma once

#include <hpx/iterator_support/traits/is_iterator.hpp>
#include <hpx/type_support/is_contiguous_iterator.hpp>
#include <hpx/type_support/is_relocatable.hpp>

#include <type_traits>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <hpx/parallel/algorithms/detail/distance.hpp>
#include <hpx/parallel/util/loop.hpp>
#include <hpx/parallel/util/result_types.hpp>
#include <hpx/type_support/is_contiguous_iterator.hpp>

#include <algorithm>
#include <cstddef>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,52 +564,4 @@ namespace hpx::traits {
template <typename Iter>
inline constexpr bool is_zip_iterator_v = is_zip_iterator<Iter>::value;

///////////////////////////////////////////////////////////////////////////
// Iterators are contiguous if they are pointers (without concepts we have
// no generic way of determining whether an iterator is contiguous)

namespace detail {

// Iterators returned from std::vector are contiguous (by definition)

// different versions of clang-format disagree
// clang-format off
template <typename Iter, typename T = iter_value_t<Iter>>
struct is_vector_iterator
: std::integral_constant<bool,
std::is_same_v<
decltype(std::declval<std::vector<T>&>().begin()), Iter> ||
std::is_same_v<
decltype(std::declval<std::vector<T>&>().cbegin()), Iter>>
{
};
// clang-format on
} // namespace detail

template <typename Iter,
bool not_vector =
// When _GLIBCXX_DEBUG is defined vectors are contiguous, but the iterators
// are not plain pointers.
#if defined(_GLIBCXX_DEBUG)
false
#else
detail::is_vector_iterator<Iter>::value
#endif
>
struct is_contiguous_iterator : std::is_pointer<Iter>::type
{
};

template <typename Iter>
struct is_contiguous_iterator<Iter, true> : std::true_type
{
};

template <typename Iter>
using is_contiguous_iterator_t =
typename is_contiguous_iterator<Iter>::type;

template <typename Iter>
inline constexpr bool is_contiguous_iterator_v =
is_contiguous_iterator<Iter>::value;
} // namespace hpx::traits
1 change: 1 addition & 0 deletions libs/core/type_support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ set(type_support_headers
hpx/type_support/identity.hpp
hpx/type_support/is_relocatable.hpp
hpx/type_support/is_trivially_relocatable.hpp
hpx/type_support/is_contiguous_iterator.hpp
hpx/type_support/lazy_conditional.hpp
hpx/type_support/lazy_enable_if.hpp
hpx/type_support/pack.hpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright (c) 2007-2022 Hartmut Kaiser
//
// SPDX-License-Identifier: BSL-1.0
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <array>
#include <iterator>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

namespace hpx::traits {
///////////////////////////////////////////////////////////////////////////
// Iterators are contiguous if they are pointers (without concepts we have
// no generic way of determining whether an iterator is contiguous)

namespace detail {

template <typename Iter>
using iter_value_type_t =
typename std::iterator_traits<Iter>::value_type;

template <typename T, typename Enable = void>
struct is_known_contiguous_iterator : std::false_type
{
};

template <typename Iter>
struct is_known_contiguous_iterator<Iter,
std::enable_if_t<!std::is_array_v<Iter>>>
: std::bool_constant<
std::is_same_v< // for std::vector
typename std::vector<iter_value_type_t<Iter>>::iterator,
Iter> ||
std::is_same_v<typename std::vector<
iter_value_type_t<Iter>>::const_iterator,
Iter> || // for std::array
std::is_same_v<
typename std::array<iter_value_type_t<Iter>, 1>::iterator,
Iter> ||
std::is_same_v<typename std::array<iter_value_type_t<Iter>,
1>::const_iterator,
Iter> || // for std::string
std::is_same_v<typename std::string::iterator, Iter> ||
std::is_same_v<typename std::string::const_iterator, Iter>>
{
};
} // namespace detail

template <typename Iter,
bool not_known_contiguous_iterator =
// When _GLIBCXX_DEBUG is defined vectors are contiguous, but the iterators
// are not plain pointers.
#if defined(_GLIBCXX_DEBUG)
false
#else
detail::is_known_contiguous_iterator<Iter>::value
#endif
>
struct is_contiguous_iterator : std::is_pointer<Iter>::type
{
};

template <typename Iter>
struct is_contiguous_iterator<Iter, true> : std::true_type
{
};

template <typename Iter>
using is_contiguous_iterator_t =
typename is_contiguous_iterator<Iter>::type;

template <typename Iter>
inline constexpr bool is_contiguous_iterator_v =
is_contiguous_iterator<Iter>::value;
} // namespace hpx::traits
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include <hpx/type_support/is_contiguous_iterator.hpp>
#include <hpx/type_support/is_relocatable.hpp>
#include <hpx/type_support/is_trivially_relocatable.hpp>
#include <hpx/type_support/relocate_at.hpp>
Expand Down Expand Up @@ -165,6 +166,7 @@ namespace hpx::experimental::util {
FwdIter uninitialized_relocate_n_primitive(InIter first, Size n,
FwdIter dst, iterators_are_contiguous_t) noexcept(
detail::relocation_traits<InIter, FwdIter>::is_noexcept_relocatable_v)
// clang-format on
{
static_assert(
detail::relocation_traits<InIter, FwdIter>::valid_relocation,
Expand All @@ -176,16 +178,15 @@ namespace hpx::experimental::util {
return detail::uninitialized_relocate_n_primitive_helper(
first, n, dst, implementation_tag{});
}
// clang-format on

template <typename InIter, typename Size, typename FwdIter>
FwdIter uninitialized_relocate_n_primitive(InIter first, Size n,
FwdIter dst) noexcept(detail::relocation_traits<InIter,
FwdIter>::is_noexcept_relocatable_v)
{
using iterators_are_contiguous_default_t =
std::bool_constant<std::is_pointer_v<InIter> &&
std::is_pointer_v<FwdIter>>;
std::bool_constant<hpx::traits::is_contiguous_iterator_v<InIter> &&
hpx::traits::is_contiguous_iterator_v<FwdIter>>;

return uninitialized_relocate_n_primitive(
first, n, dst, iterators_are_contiguous_default_t{});
Expand Down
4 changes: 3 additions & 1 deletion libs/core/type_support/tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ endforeach()

if(HPX_WITH_COMPILE_ONLY_TESTS)
# add compile time tests
set(compile_tests is_relocatable is_trivially_relocatable)
set(compile_tests is_relocatable is_trivially_relocatable
is_contiguous_iterator
)

if(HPX_WITH_FAIL_COMPILE_TESTS)
set(fail_compile_tests fail_relocate_at fail_uninitialized_relocate)
Expand Down
49 changes: 49 additions & 0 deletions libs/core/type_support/tests/unit/is_contiguous_iterator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 2023 Isidoros Tsaousis-Seiras
//
// SPDX-License-Identifier: BSL-1.0
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <array>
#include <cassert>
#include <vector>

#include <hpx/type_support/is_contiguous_iterator.hpp>

using hpx::traits::is_contiguous_iterator_v;

// std::vector<int>::iterator is a contiguous iterator
static_assert(is_contiguous_iterator_v<std::vector<int>::iterator>);
static_assert(is_contiguous_iterator_v<std::vector<int>::const_iterator>);
// reverse_iterator is not a contiguous iterator
static_assert(!is_contiguous_iterator_v<std::vector<int>::reverse_iterator>);
static_assert(
!is_contiguous_iterator_v<std::vector<int>::const_reverse_iterator>);

// std::array<int, 4>::iterator is a contiguous iterator
static_assert(is_contiguous_iterator_v<std::array<int, 4>::iterator>);
static_assert(is_contiguous_iterator_v<std::array<int, 4>::const_iterator>);
// reverse_iterator is not a contiguous iterator
static_assert(!is_contiguous_iterator_v<std::array<int, 4>::reverse_iterator>);
static_assert(
!is_contiguous_iterator_v<std::array<int, 4>::const_reverse_iterator>);

// pointers are contiguous iterators
static_assert(is_contiguous_iterator_v<int*>);
static_assert(is_contiguous_iterator_v<int const*>);
static_assert(is_contiguous_iterator_v<int (*)[]>);
static_assert(is_contiguous_iterator_v<int const (*)[]>);
static_assert(is_contiguous_iterator_v<int (*)[4]>);
static_assert(is_contiguous_iterator_v<int const (*)[4]>);

// arrays are not contiguous iterators
static_assert(!is_contiguous_iterator_v<int[]>);
static_assert(!is_contiguous_iterator_v<int[4]>);
static_assert(!is_contiguous_iterator_v<int const[]>);
static_assert(!is_contiguous_iterator_v<int const[4]>);

// std::string::iterator is a contiguous iterator
static_assert(is_contiguous_iterator_v<std::string::iterator>);
static_assert(is_contiguous_iterator_v<std::string::const_iterator>);

int main(int, char*[]) {}

0 comments on commit a43f622

Please sign in to comment.