Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P3168R1: use a non-pointer iterator type #18

Merged
merged 17 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# /CMakeLists.txt -*-makefile-*-
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

cmake_minimum_required(VERSION 3.10)

project(beman_optional26 VERSION 0.0.0 LANGUAGES CXX)
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#! /usr/bin/make -f
# -*-makefile-*-
# /Makefile -*-makefile-*-
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

INSTALL_PREFIX?=.install/
PROJECT?=$(shell basename $(CURDIR))
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# Beman.Optional26: C++26 Extensions for std::optional

<!--
SPDX-License-Identifier: 2.0 license with LLVM exceptions
-->

This implementation incorporates the C++26 extensions added for `std::optional`. The `Beman.Optional26` library aims to evaluate the stability, the usability, and the performance of these proposed changes before they are officially adopted by WG21 into the C++ Working Draft. Additionally, it allows developers to use these new features before they are implemented in major standard library compilers.

**Implements**:
* [`std::optional<T&>` (P2988R5)](https://wg21.link/P2988R5)
* [Give *std::optional* Range Support (P3168R1)](https://wg21.link/P3168R1).

## License

Source is licensed with the Apache 2.0 license with LLVM exceptions

Expand Down
3 changes: 3 additions & 0 deletions cmake/Config.cmake.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# cmake/Config.cmake.in -*-makefile-*-
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
Expand Down
2 changes: 1 addition & 1 deletion etc/gcc-flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include_guard(GLOBAL)
set(CMAKE_CXX_STANDARD 23)

set(CMAKE_CXX_FLAGS
"-Wall -Wextra "
"-std=c++23 -Wall -Wextra "
CACHE STRING "CXX_FLAGS" FORCE)

set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE)
Expand Down
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# examples/CMakeLists.txt -*-makefile-*-
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

set(BEMAN_OPTIONAL26_LIBRARY "beman_optional26")

include(GNUInstallDirs)
Expand Down
19 changes: 19 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
# Beman.Optional26 Examples

<!--
SPDX-License-Identifier: 2.0 license with LLVM exceptions
-->

List of usage examples for `Beman.Optional26`.

## License
Source is licensed with the Apache 2.0 license with LLVM exceptions

// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

Documentation and associated papers are licensed with the Creative Commons Attribution 4.0 International license.

// SPDX-License-Identifier: CC-BY-4.0

The intent is that the source and documentation are available for use by people implementing their own optional types as well as people using the optional presented here as-is.

The README itself is licesed with CC0 1.0 Universal. Copy the contents and incorporate in your own work as you see fit.

// SPDX-License-Identifier: CC0-1.0

## Sample

Check [sample](sample.cpp) for basic `Beman.Optional26` library usage.
Expand Down
3 changes: 3 additions & 0 deletions examples/optional_ref.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// examples/optional_ref.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <Beman/Optional26/optional.hpp>

#include <string>
Expand Down
3 changes: 3 additions & 0 deletions examples/range_loop.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// examples/range_loop.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <Beman/Optional26/optional.hpp>
#include <iostream>

Expand Down
3 changes: 3 additions & 0 deletions examples/sample.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// examples/sample.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <Beman/Optional26/optional.hpp>
#include <iostream>

Expand Down
3 changes: 3 additions & 0 deletions extern/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
# extern/CMakeLists.txt -*-makefile-*-
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

add_subdirectory(googletest EXCLUDE_FROM_ALL)
56 changes: 56 additions & 0 deletions include/Beman/Optional26/detail/iterator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// include/Beman/Optional26/detail/iterator.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef BEMAN_OPTIONAL26_DETAIL_ITERATOR_HPP
#define BEMAN_OPTIONAL26_DETAIL_ITERATOR_HPP

#include <Beman/Optional26/detail/stl_interfaces/iterator_interface.hpp>

#include <iterator>

namespace beman::optional::detail {

// This is a minimal contiguous iterator. It uses stl_interfaces library from Boost
// (current implementation based on https://wg21.link/P2727R4).
//
// TODO: Change this to use the stl_interfaces library from Beman when available.
//
// @tparam T - The type of the elements the iterator points to.
// @tparam Container - The type of the container the iterator points to. This parameter exists solely so that different
// containers using this template can instantiate different types, even if the T parameter is the same.
template <class T, class Container>
struct contiguous_iterator : stl_interfaces::iterator_interface<
#if !BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS
contiguous_iterator<T, Container>,
#endif
std::contiguous_iterator_tag,
T> {
using iterator_type = T*;
using iterator_category = std::iterator_traits<iterator_type>::iterator_category;
using iterator_concept = std::iterator_traits<iterator_type>::iterator_concept;
using value_type = std::iterator_traits<iterator_type>::value_type;
using difference_type = std::iterator_traits<iterator_type>::difference_type;
using reference = std::iterator_traits<iterator_type>::reference;
using pointer = std::iterator_traits<iterator_type>::pointer;

// Default constructor.
contiguous_iterator() noexcept : m_current() {}

// Pointer to iterator constructor.
contiguous_iterator(pointer it) noexcept : m_current(it) {}

// As per P2727R4, for contiguous iterator we only need to provide operator*, operator+= and operator-.
reference operator*() const noexcept { return *m_current; }
auto& operator+=(difference_type pos) noexcept {
m_current += pos;
return *this;
}
difference_type operator-(contiguous_iterator other) const noexcept { return m_current - other.m_current; }

private:
T* m_current;
};

} // namespace beman::optional::detail

#endif // BEMAN_OPTIONAL26_DETAIL_ITERATOR_HPP
49 changes: 49 additions & 0 deletions include/Beman/Optional26/detail/stl_interfaces/config.hpp
Original file line number Diff line number Diff line change
@@ -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 <iterator>

#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
88 changes: 88 additions & 0 deletions include/Beman/Optional26/detail/stl_interfaces/fwd.hpp
Original file line number Diff line number Diff line change
@@ -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 <Beman/Optional26/detail/stl_interfaces/config.hpp>

#if BEMAN_OPTIONAL26_DETAIL_STL_INTERFACES_USE_CONCEPTS
#include <ranges>
#endif
#if defined(__cpp_lib_three_way_comparison)
#include <compare>
#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::optional::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 <typename... T>
using void_t = void;

template <typename Iter>
using iter_difference_t = typename std::iterator_traits<Iter>::difference_type;

template <typename Range, typename = void>
struct iterator;
template <typename Range>
struct iterator<Range, void_t<decltype(std::declval<Range&>().begin())>> {
using type = decltype(std::declval<Range&>().begin());
};
template <typename Range>
using iterator_t = typename iterator<Range>::type;

template <typename Range, typename = void>
struct sentinel;
template <typename Range>
struct sentinel<Range, void_t<decltype(std::declval<Range&>().end())>> {
using type = decltype(std::declval<Range&>().end());
};
template <typename Range>
using sentinel_t = typename sentinel<Range>::type;

template <typename Range>
using range_difference_t = iter_difference_t<iterator_t<Range>>;

template <typename Range>
using common_range = std::is_same<iterator_t<Range>, sentinel_t<Range>>;

template <typename Range, typename = void>
struct decrementable_sentinel : std::false_type {};
template <typename Range>
struct decrementable_sentinel<Range, void_t<decltype(--std::declval<sentinel_t<Range>&>())>> : std::true_type {};
} // namespace v1_dtl
}
} // namespace stl_interfaces
} // namespace beman::optional::detail

#endif
Loading
Loading