From 843054cefb4f2d38e1531efedffc3f9e78876cc6 Mon Sep 17 00:00:00 2001 From: David Sankel Date: Fri, 18 Oct 2024 15:44:40 -0400 Subject: [PATCH] Add stl_interfaces fallback when deducing this is unavailable. Added a build option, BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS, that switches between the deducing this implementation and that used by stl_interfaces. It defaults to whether the compiler supports deducing this. This element of configuration is placed in a generated config.hpp. This was chosen, as opposed to using a define passed as a compiler flag, to avoid ODR violations with larger projects with incoherent flag usage. The `iterator_interface_access` struct was moved to its own header since it is needed by both the deducing this and stl_interfaces implementations. The stl_interfaces implementation was modifed to use this so it better conforms to the paper. Some cleanup is still needed before this gets merged in: - There are optional26 remnants where stl_interfaces was brought in from. - Documentation is needed to explain when the extra template parameter is required. BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS() should probably also be mentioned in that context. The intent is to address these once the overall approach has consensus. Fixes #10 and depends on #12. --- CMakeLists.txt | 14 +- .../beman/iterator_interface26/config.hpp.in | 6 + .../detail/stl_interfaces/config.hpp | 49 + .../detail/stl_interfaces/fwd.hpp | 88 ++ .../stl_interfaces/iterator_interface.hpp | 970 ++++++++++++++++++ .../iterator_interface.hpp | 35 +- .../iterator_interface_access.hpp | 23 + src/beman/iterator_interface26/CMakeLists.txt | 3 +- .../iterator_interface.t.cpp | 28 +- 9 files changed, 1192 insertions(+), 24 deletions(-) create mode 100644 include/beman/iterator_interface26/config.hpp.in create mode 100644 include/beman/iterator_interface26/detail/stl_interfaces/config.hpp create mode 100644 include/beman/iterator_interface26/detail/stl_interfaces/fwd.hpp create mode 100644 include/beman/iterator_interface26/detail/stl_interfaces/iterator_interface.hpp create mode 100644 include/beman/iterator_interface26/iterator_interface_access.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0262a45..49d3aab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,10 +8,20 @@ include(CompilerFeatureTest) beman_iterator26_check_deducing_this(COMPILER_SUPPORTS_DEDUCING_THIS) -if(NOT COMPILER_SUPPORTS_DEDUCING_THIS) - message(FATAL_ERROR "The selected compiler and flags lack C++23's deducing this support, which is required to build this project. Try adding -DCMAKE_CXX_STANDARD=23 to your command line parameters and, failing that, upgrade your compiler.") +option(BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS + "Make use of deducing this. Turn this off for non-conforming compilers." + ${COMPILER_SUPPORTS_DEDUCING_THIS}) + +if(BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS AND NOT COMPILER_SUPPORTS_DEDUCING_THIS) + message(WARNING "Building with deducing this support despite of the compiler's lack of support for it") endif() +configure_file( + "${PROJECT_SOURCE_DIR}/include/beman/iterator_interface26/config.hpp.in" + "${PROJECT_BINARY_DIR}/include/beman/iterator_interface26/config.hpp" + @ONLY +) + enable_testing() set(TARGETS_EXPORT_NAME ${CMAKE_PROJECT_NAME}Targets) diff --git a/include/beman/iterator_interface26/config.hpp.in b/include/beman/iterator_interface26/config.hpp.in new file mode 100644 index 0000000..b83cd27 --- /dev/null +++ b/include/beman/iterator_interface26/config.hpp.in @@ -0,0 +1,6 @@ +#ifndef BEMAN_ITERATOR_INTERFACE26_CONFIG_HPP +#define BEMAN_ITERATOR_INTERFACE26_CONFIG_HPP + +#cmakedefine01 BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS() + +#endif diff --git a/include/beman/iterator_interface26/detail/stl_interfaces/config.hpp b/include/beman/iterator_interface26/detail/stl_interfaces/config.hpp new file mode 100644 index 0000000..68ad40c --- /dev/null +++ b/include/beman/iterator_interface26/detail/stl_interfaces/config.hpp @@ -0,0 +1,49 @@ +// include/beman/optional26/detail/stl_interfaces/config.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Copyright (C) 2020 T. Zachary Laine +// +// 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) +#ifndef BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_CONFIG_HPP +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_CONFIG_HPP + +// Included for definition of __cpp_lib_concepts. +#include + +#if defined(__cpp_lib_concepts) && defined(__cpp_lib_ranges) && \ + !defined(BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_DISABLE_CONCEPTS) +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS 1 +#else +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS 0 +#endif + +#if defined(__cpp_explicit_this_parameter) && BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS && \ + !defined(BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_DISABLE_DEDUCED_THIS) +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS 1 +#else +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS 0 +#endif + +// The inline namespaces v1, v2, and v3 represent C++14, C++20, and C++23 and +// later, respectively. v1 is inline for standards before C++20, and v2 is +// inline for C++20 and later. Note that this only applies to code for which +// multiple vI namespace alternatives exist. For example, some instances of +// the v1 namespace may still be inline, if there is no v2 version of its +// contents. +#if !BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS && !BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V1 inline namespace v1 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V2 namespace v2 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V3 namespace v3 +#elif BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS && !BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V1 namespace v1 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V2 inline namespace v2 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V3 namespace v3 +#else +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V1 namespace v1 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V2 namespace v2 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V3 inline namespace v3 +#endif + +#endif diff --git a/include/beman/iterator_interface26/detail/stl_interfaces/fwd.hpp b/include/beman/iterator_interface26/detail/stl_interfaces/fwd.hpp new file mode 100644 index 0000000..2ea5a8f --- /dev/null +++ b/include/beman/iterator_interface26/detail/stl_interfaces/fwd.hpp @@ -0,0 +1,88 @@ +// include/beman/optional26/detail/stl_interfaces/fwd.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Copyright (C) 2019 T. Zachary Laine +// +// 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) +#ifndef BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_FWD_HPP +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_FWD_HPP + +#include + +#if BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS +#include +#endif +#if defined(__cpp_lib_three_way_comparison) +#include +#endif + +#ifndef BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_DOXYGEN + +#if defined(_MSC_VER) || defined(__GNUC__) && __GNUC__ < 8 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NO_HIDDEN_FRIEND_CONSTEXPR +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR +#else +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR constexpr +#endif + +#if defined(__GNUC__) && __GNUC__ < 9 +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_CONCEPT concept bool +#else +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_CONCEPT concept +#endif + +#endif + +namespace beman::iterator_interface26::detail { +namespace stl_interfaces { + +/** An enumeration used to indicate whether the underlying data have a + contiguous or discontiguous layout when instantiating `view_interface` + and `sequence_container_interface`. */ +enum class element_layout : bool { discontiguous = false, contiguous = true }; + +BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_NAMESPACE_V1 { + + namespace v1_dtl { + template + using void_t = void; + + template + using iter_difference_t = typename std::iterator_traits::difference_type; + + template + struct iterator; + template + struct iterator().begin())>> { + using type = decltype(std::declval().begin()); + }; + template + using iterator_t = typename iterator::type; + + template + struct sentinel; + template + struct sentinel().end())>> { + using type = decltype(std::declval().end()); + }; + template + using sentinel_t = typename sentinel::type; + + template + using range_difference_t = iter_difference_t>; + + template + using common_range = std::is_same, sentinel_t>; + + template + struct decrementable_sentinel : std::false_type {}; + template + struct decrementable_sentinel&>())>> : std::true_type {}; + } // namespace v1_dtl +} +} // namespace stl_interfaces +} // namespace beman::optional26::detail + +#endif diff --git a/include/beman/iterator_interface26/detail/stl_interfaces/iterator_interface.hpp b/include/beman/iterator_interface26/detail/stl_interfaces/iterator_interface.hpp new file mode 100644 index 0000000..2ab8e09 --- /dev/null +++ b/include/beman/iterator_interface26/detail/stl_interfaces/iterator_interface.hpp @@ -0,0 +1,970 @@ +// include/beman/optional26/detail/stl_interfaces/iterator_interface.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Copyright (C) 2019 T. Zachary Laine +// +// 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) +#ifndef BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_ITERATOR_INTERFACE_HPP +#define BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_ITERATOR_INTERFACE_HPP + +#include +#include + +#include +#include +#if defined(__cpp_lib_three_way_comparison) +#include +#endif + +namespace beman::iterator_interface26::detail { +namespace stl_interfaces { + +/** The return type of `operator->()` in a proxy iterator. + + This template is used as the default `Pointer` template parameter in + the `proxy_iterator_interface` template alias. Note that the use of + this template implies a copy or move of the underlying object of type + `T`. */ +template +#if defined(BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_DOXYGEN) || BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS +// clang-format off + requires std::is_object_v +#endif + struct proxy_arrow_result +// clang-format on +{ + constexpr proxy_arrow_result(const T& value) noexcept(noexcept(T(value))) : value_(value) {} + constexpr proxy_arrow_result(T&& value) noexcept(noexcept(T(std::move(value)))) : value_(std::move(value)) {} + + constexpr const T* operator->() const noexcept { return &value_; } + constexpr T* operator->() noexcept { return &value_; } + + private: + T value_; +}; + +namespace detail { +template +auto make_pointer(T&& value, + std::enable_if_t::value && std::is_reference::value, int> = 0) + -> decltype(std::addressof(value)) { + return std::addressof(value); +} + +template +auto make_pointer(T&& value, + std::enable_if_t::value && !std::is_same::value && + std::is_reference::value, + int> = 0) { + return Pointer(std::forward(value)); +} + +template +struct pointer { + using type = Pointer; +}; +template +struct pointer { + using type = void; +}; +template +using pointer_t = typename pointer::type; + +template +using interoperable = + std::integral_constant::value || std::is_convertible::value)>; + +template +using common_t = std::conditional_t::value, U, T>; + +template +using use_base = decltype(iterator_interface_access::base(std::declval())); + +template +using void_t = void; + +template class Template, typename... Args> +struct detector : std::false_type {}; + +template