diff --git a/CMakeLists.txt b/CMakeLists.txt
index 774ba0a..477ae42 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,8 +27,11 @@ option(BEMAN_ITERATOR_INTERFACE_USE_DEDUCING_THIS
"Make use of C++23 \"deducing this\" feature (P0847R7). Turn this off for non-conforming compilers."
${COMPILER_SUPPORTS_DEDUCING_THIS})
-option(ITERATOR_INTERFACE_ENABLE_TESTING
- "Enable building tests and test infrastructure" ${PROJECT_IS_TOP_LEVEL})
+option(BEMAN_ITERATOR_INTERFACE_BUILD_TESTS
+ "Enable building tests and test infrastructure. Default: ON. Values: {ON, OFF}." ${PROJECT_IS_TOP_LEVEL})
+
+option(BEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES
+ "Enable building examples. Default: ON. Values: {ON, OFF}." ${PROJECT_IS_TOP_LEVEL})
if(BEMAN_ITERATOR_INTERFACE_USE_DEDUCING_THIS
AND NOT COMPILER_SUPPORTS_DEDUCING_THIS)
@@ -42,8 +45,7 @@ configure_file(
"${PROJECT_SOURCE_DIR}/include/beman/iterator_interface/config.hpp.in"
"${PROJECT_BINARY_DIR}/include/beman/iterator_interface/config.hpp" @ONLY)
-# Build the tests if enabled via the option ITERATOR_INTERFACE_ENABLE_TESTING
-if(ITERATOR_INTERFACE_ENABLE_TESTING)
+if(BEMAN_ITERATOR_INTERFACE_BUILD_TESTS)
# Fetch GoogleTest
FetchContent_Declare(
googletest
@@ -79,11 +81,15 @@ target_include_directories(
add_subdirectory(src/beman/iterator_interface)
add_subdirectory(include/beman/iterator_interface)
-add_subdirectory(examples)
-if(ITERATOR_INTERFACE_ENABLE_TESTING)
+if(BEMAN_ITERATOR_INTERFACE_BUILD_TESTS)
+ enable_testing()
add_subdirectory(tests/beman/iterator_interface)
endif()
+if(BEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES)
+ add_subdirectory(examples)
+endif()
+
# Coverage
configure_file("cmake/gcovr.cfg.in" gcovr.cfg @ONLY)
diff --git a/CMakePresets.json b/CMakePresets.json
index a23297c..d035bef 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -1,143 +1,68 @@
{
"version": 6,
- "cmakeMinimumRequired": {
- "major": 3,
- "minor": 29,
- "patch": 2
- },
"configurePresets": [
{
- "name": "common",
- "description": "General settings that apply to all configurations",
+ "name": "_root-config",
"hidden": true,
- "generator": "Ninja Multi-Config",
+ "generator": "Ninja",
"binaryDir": "${sourceDir}/.build/${presetName}",
- "installDir": "${sourceDir}/.install/${presetName}",
"cacheVariables": {
- "CMAKE_CONFIGURATION_TYPES": "RelWithDebInfo;Debug;Tsan;Asan"
+ "CMAKE_CXX_STANDARD": "20"
}
},
{
- "name": "system",
- "inherits": "common",
- "displayName": "System compiler",
- "description": "Build with default cc and c++ compilers",
- "toolchainFile": "${sourceDir}/etc/toolchain.cmake"
- },
- {
- "name": "gcc-14",
- "inherits": "common",
- "displayName": "GCC 14",
- "description": "Build with GCC 14 compilers",
- "toolchainFile": "${sourceDir}/etc/gcc-14-toolchain.cmake"
- },
- {
- "name": "gcc-13",
- "inherits": "common",
- "displayName": "GCC 13",
- "description": "Build with GCC 13 compilers",
- "toolchainFile": "${sourceDir}/etc/gcc-13-toolchain.cmake"
- },
- {
- "name": "gcc-12",
- "inherits": "common",
- "displayName": "GCC 12",
- "description": "Build with GCC 12 compilers",
- "toolchainFile": "${sourceDir}/etc/gcc-12-toolchain.cmake"
- },
- {
- "name": "clang-20",
- "inherits": "common",
- "displayName": "Clang 20",
- "description": "Build with Clang 20 compilers",
- "toolchainFile": "${sourceDir}/etc/clang-20-toolchain.cmake"
- },
- {
- "name": "clang-19",
- "inherits": "common",
- "displayName": "Clang 19",
- "description": "Build with Clang 19 compilers",
- "toolchainFile": "${sourceDir}/etc/clang-19-toolchain.cmake"
+ "name": "_debug-base",
+ "hidden": true,
+ "cacheVariables": {
+ "CMAKE_BUILD_TYPE": "Debug",
+ "CMAKE_CXX_FLAGS": "-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=leak -fsanitize=undefined"
+ }
},
{
- "name": "clang-18",
- "inherits": "common",
- "displayName": "Clang 18",
- "description": "Build with Clang 18 compilers",
- "toolchainFile": "${sourceDir}/etc/clang-18-toolchain.cmake"
+ "name": "_release-base",
+ "hidden": true,
+ "cacheVariables": {
+ "CMAKE_BUILD_TYPE": "RelWithDebInfo",
+ "CMAKE_CXX_FLAGS": "-O3"
+ }
},
{
- "name": "clang-17",
- "inherits": "common",
- "displayName": "Clang 17",
- "description": "Build with Clang 17 compilers",
- "toolchainFile": "${sourceDir}/etc/clang-17-toolchain.cmake"
+ "name": "gcc-debug",
+ "displayName": "GCC Debug Build",
+ "inherits": [
+ "_root-config",
+ "_debug-base"
+ ],
+ "cacheVariables": {
+ "CMAKE_CXX_COMPILER": "g++"
+ }
},
{
- "name": "clang-16",
- "inherits": "common",
- "displayName": "Clang 16",
- "description": "Build with Clang 16 compilers",
- "toolchainFile": "${sourceDir}/etc/clang-16-toolchain.cmake"
+ "name": "gcc-release",
+ "displayName": "GCC Release Build",
+ "inherits": [
+ "_root-config",
+ "_release-base"
+ ],
+ "cacheVariables": {
+ "CMAKE_CXX_COMPILER": "g++"
+ }
}
],
"buildPresets": [
{
- "name": "common",
- "hidden": true,
- "configuration": "Asan"
- },
- {
- "name": "system",
- "inherits": "common",
- "configurePreset": "system"
- },
- {
- "name": "gcc-14",
- "inherits": "common",
- "configurePreset": "gcc-14"
- },
- {
- "name": "gcc-13",
- "inherits": "common",
- "configurePreset": "gcc-13"
+ "name": "gcc-debug",
+ "configurePreset": "gcc-debug"
},
{
- "name": "gcc-12",
- "inherits": "common",
- "configurePreset": "gcc-12"
- },
- {
- "name": "clang-20",
- "inherits": "common",
- "configurePreset": "clang-20"
- },
- {
- "name": "clang-19",
- "inherits": "common",
- "configurePreset": "clang-19"
- },
- {
- "name": "clang-18",
- "inherits": "common",
- "configurePreset": "clang-18"
- },
- {
- "name": "clang-17",
- "inherits": "common",
- "configurePreset": "clang-17"
- },
- {
- "name": "clang-16",
- "inherits": "common",
- "configurePreset": "clang-16"
+ "name": "gcc-release",
+ "configurePreset": "gcc-release"
}
],
"testPresets": [
{
- "name": "common",
+ "name": "_test_base",
"hidden": true,
- "configuration": "Asan",
"output": {
"outputOnFailure": true
},
@@ -147,205 +72,50 @@
}
},
{
- "name": "system",
- "inherits": "common",
- "configurePreset": "system"
- },
- {
- "name": "gcc-14",
- "inherits": "common",
- "configurePreset": "gcc-14"
- },
- {
- "name": "gcc-13",
- "inherits": "common",
- "configurePreset": "gcc-13"
- },
- {
- "name": "gcc-12",
- "inherits": "common",
- "configurePreset": "gcc-12"
- },
- {
- "name": "clang-20",
- "inherits": "common",
- "configurePreset": "clang-20"
+ "name": "gcc-debug",
+ "inherits": "_test_base",
+ "configurePreset": "gcc-debug"
},
{
- "name": "clang-19",
- "inherits": "common",
- "configurePreset": "clang-19"
- },
- {
- "name": "clang-18",
- "inherits": "common",
- "configurePreset": "clang-18"
- },
- {
- "name": "clang-17",
- "inherits": "common",
- "configurePreset": "clang-17"
- },
- {
- "name": "clang-16",
- "inherits": "common",
- "configurePreset": "clang-16"
+ "name": "gcc-release",
+ "inherits": "_test_base",
+ "configurePreset": "gcc-release"
}
],
"workflowPresets": [
{
- "name": "system",
- "steps": [
- {
- "type": "configure",
- "name": "system"
- },
- {
- "type": "build",
- "name": "system"
- },
- {
- "type": "test",
- "name": "system"
- }
- ]
- },
- {
- "name": "gcc-14",
- "steps": [
- {
- "type": "configure",
- "name": "gcc-14"
- },
- {
- "type": "build",
- "name": "gcc-14"
- },
- {
- "type": "test",
- "name": "gcc-14"
- }
- ]
- },
- {
- "name": "gcc-13",
- "steps": [
- {
- "type": "configure",
- "name": "gcc-13"
- },
- {
- "type": "build",
- "name": "gcc-13"
- },
- {
- "type": "test",
- "name": "gcc-13"
- }
- ]
- },
- {
- "name": "gcc-12",
- "steps": [
- {
- "type": "configure",
- "name": "gcc-12"
- },
- {
- "type": "build",
- "name": "gcc-12"
- },
- {
- "type": "test",
- "name": "gcc-12"
- }
- ]
- },
- {
- "name": "clang-20",
- "steps": [
- {
- "type": "configure",
- "name": "clang-20"
- },
- {
- "type": "build",
- "name": "clang-20"
- },
- {
- "type": "test",
- "name": "clang-20"
- }
- ]
- },
- {
- "name": "clang-19",
- "steps": [
- {
- "type": "configure",
- "name": "clang-19"
- },
- {
- "type": "build",
- "name": "clang-19"
- },
- {
- "type": "test",
- "name": "clang-19"
- }
- ]
- },
- {
- "name": "clang-18",
- "steps": [
- {
- "type": "configure",
- "name": "clang-18"
- },
- {
- "type": "build",
- "name": "clang-18"
- },
- {
- "type": "test",
- "name": "clang-18"
- }
- ]
- },
- {
- "name": "clang-17",
+ "name": "gcc-debug",
"steps": [
{
"type": "configure",
- "name": "clang-17"
+ "name": "gcc-debug"
},
{
"type": "build",
- "name": "clang-17"
+ "name": "gcc-debug"
},
{
"type": "test",
- "name": "clang-17"
+ "name": "gcc-debug"
}
]
},
{
- "name": "clang-16",
+ "name": "gcc-release",
"steps": [
{
"type": "configure",
- "name": "clang-16"
+ "name": "gcc-release"
},
{
"type": "build",
- "name": "clang-16"
+ "name": "gcc-release"
},
{
"type": "test",
- "name": "clang-16"
+ "name": "gcc-release"
}
]
}
]
}
-
diff --git a/README.md b/README.md
index af99b07..765c4f4 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,7 @@ SPDX-License-Identifier: 2.0 license with LLVM exceptions

**Implements**:
-* [`std::iterator_interface` (P2727)](https://wg21.link/P2727)
-
+* [`std::iterator_interface` (P2727R4)](https://wg21.link/P2727R4)
Source is licensed with the Apache 2.0 license with LLVM exceptions
@@ -18,53 +17,379 @@ Documentation and associated papers are licensed with the Creative Commons Attri
// 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 intent is that the source and documentation are available for use by people implementing their iterator types.
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
+## Examples
+
+Full runable examples can be found in `examples/` - please check [./examples/README.md](./examples/README.md) for building the code on local setup or on Compiler Explorer.
+
+### Repetead Chars Iterator
+
+The next code snippet shows iterator interface support added in [`std::iterator_interface` (P2727R)](https://wg21.link/P2727R4): define a random access iterator that iterates over a sequence of characters repeated indefinitely.
+
+```cpp
+// Create a repeated_chars_iterator that iterates over the sequence "foo" repeated indefinitely:
+// "foofoofoofoofoofoo...". Will actually extract a prefix of the sequence and insert it into a std::string.
+constexpr const std::string_view target = "foo";
+constexpr const auto len = 7; // Number of extracted characters from the sequence.
+
+// Create iterators that iterate over the sequence "foofoofoofoofoofoo...".
+repeated_chars_iterator it_first(target.data(), target.size(), 0); // target.size() == 3 is the length of "foo", 0 is this iterator's position.
+repeated_chars_iterator it_last(target.data(), target.size(), len); // Same as above, but now the iterator's position is 7.
+
+std::string extracted_result;
+std::copy(it_first, it_last, std::back_inserter(extracted_result));
+assert(extracted_result.size() == len);
+std::cout << extracted_result << "\n"; // Expected output at STDOUT: "foofoof"
+```
+
+### Filter Integer Iterator
+
+The next code snippet shows iterator interface support added in [`std::iterator_interface` (P2727R4)](https://wg21.link/P2727R4): define a forward iterator that iterates over a sequence of integers, skipping those that do not satisfy a predicate.
+
+```cpp
+// Create a filtered_int_iterator that iterates over the sequence {1, 2, 3, 4, 10, 11, 101, 200, 0},
+// skipping odd numbers. 0 is not skipped, so it will be the last element in the sequence.
+std::array a = {1, 2, 3, 4, 10, 11, 101, 200, 0};
+filtered_int_iterator it{std::begin(a), std::end(a), [](int i) { return i % 2 == 0; }};
+
+while (*it) {
+ std::cout << *it << " ";
+ ++it;
+}
+std::cout << "\n";
+```
+
## How to Build
+### Compiler Support
+
+This is a modern C++ project which can be compiled with the latest C++ standards (**C++20 or later**).
+
+Default build: `C++23`. Please check `etc/${compiler}-flags.cmake`.
+
### Dependencies
-This project is mainly tested on `Ubuntu 22.04` and `Ubuntu 24.04`, but it should be as portable as CMake is. This project has zero C or C++ dependencies.
+This project is mainly tested on `Ubuntu 22.04` and `Ubuntu 24.04`, but it should be as portable as CMake is. This
+project has no C or C++ dependencies.
-It does require few tools as build-time dependencies:
+Build-time dependencies:
-- `cmake`
-- `ninja`, `make`, or another CMake-supported build system
- - CMake defaults to "Unix Makefiles" on POSIX systems
+* `cmake`
+* `ninja`, `make`, or another CMake-supported build system
+ * CMake defaults to "Unix Makefiles" on POSIX systems
Example of installation on `Ubuntu 24.04`:
+
```shell
-# install tools
+# Install tools:
apt-get install -y cmake make ninja-build
-# example of toolchains
-apt-get install g++-14 gcc-14 clang-18 clang++-18
+# Example of toolchains:
+apt-get install \
+ g++-14 gcc-14 gcc-13 g++-14 \
+ clang-18 clang++-18 clang-17 clang++-17
```
### Instructions
-Full set of supported toolchains can be found in [.github/workflows/ci.yml](#.github/workflows/ci.yml).
+#### Preset CMake Flows
+
+This project strives to be as normal and simple a CMake project as possible. This build workflow in particular will
+work, producing a static `beman.iterator_interface` library, ready to package:
+
+```shell
+$ cmake --workflow --preset gcc-debug
+$ cmake --workflow --preset gcc-release
+$ cmake --install .build/gcc-release --prefix /opt/beman.iterator_interface
+
+$ tree /opt/beman.iterator_interface
+├── bin # examples (check: BEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES - default: ON)
+│ ├── beman.iterator_interface.examples.filter_int_iterator
+│ └── beman.iterator_interface.examples.repeated_chars_iterator
+├── include # public API
+│ └── beman
+│ └── iterator_interface
+│ ├── config.hpp
+│ ├── detail
+│ │ └── stl_interfaces
+│ │ ├── config.hpp
+│ │ ├── fwd.hpp
+│ │ └── iterator_interface.hpp
+│ ├── iterator_interface.hpp
+│ └── iterator_interface_access.hpp
+└── lib # actual library implementation
+ └── libbeman.iterator_interface.a
+
+8 directories, 9 files
+```
+
+
+ Build beman.iterator_interface (verbose logs - gcc-debug)
+
+
+This should build and run the tests with system GCC with the address and undefined behavior sanitizers enabled.
+
+```shell
+$ cmake --workflow --preset gcc-debug
+Executing workflow step 1 of 3: configure preset "gcc-debug"
+
+Preset CMake variables:
+
+ CMAKE_BUILD_TYPE="Debug"
+ CMAKE_CXX_COMPILER="g++"
+ CMAKE_CXX_FLAGS="-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=leak -fsanitize=undefined"
+ CMAKE_CXX_STANDARD="17"
+
+-- The CXX compiler identification is GNU 13.2.0
+-- Detecting CXX compiler ABI info
+-- Detecting CXX compiler ABI info - done
+-- Check for working CXX compiler: /usr/bin/g++ - skipped
+-- Detecting CXX compile features
+-- Detecting CXX compile features - done
+-- Performing Test HAVE_DEDUCING_THIS
+-- Performing Test HAVE_DEDUCING_THIS - Failed
+-- The C compiler identification is GNU 13.2.0
+-- Detecting C compiler ABI info
+-- Detecting C compiler ABI info - done
+-- Check for working C compiler: /usr/bin/cc - skipped
+-- Detecting C compile features
+-- Detecting C compile features - done
+-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
+-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
+-- Found Threads: TRUE
+-- Configuring done (2.7s)
+-- Generating done (0.0s)
+-- Build files have been written to: /path/to/repo/.build/gcc-debug
+
+Executing workflow step 2 of 3: build preset "gcc-debug"
+
+[15/15] Linking CXX executable tests/beman/iterator_interface/beman.iterator_interface.tests
+
+Executing workflow step 3 of 3: test preset "gcc-debug"
+
+Test project /path/to/repo/.build/gcc-debug
+ Start 1: IteratorTest.TestGTest
+1/4 Test #1: IteratorTest.TestGTest ........... Passed 0.01 sec
+ Start 2: IteratorTest.TestRepeatedChars
+2/4 Test #2: IteratorTest.TestRepeatedChars ... Passed 0.01 sec
+ Start 3: IteratorTest.TestFilteredIter
+3/4 Test #3: IteratorTest.TestFilteredIter .... Passed 0.01 sec
+ Start 4: IteratorTest.OperatorArrow
+4/4 Test #4: IteratorTest.OperatorArrow ....... Passed 0.01 sec
+
+100% tests passed, 0 tests failed out of 4
+
+Total Test time (real) = 0.04 sec
+```
+
+
-#### Basic Build
-This project strives to be as normal and simple a CMake project as possible. This build workflow in particular will work, producing a static `beman_optional26` library, ready to package:
+
+ Install beman.iterator_interface (verbose logs - gcc-release)
```shell
-cmake --workflow --preset gcc-14
+# Build release.
+$ cmake --workflow --preset gcc-release
+Executing workflow step 1 of 3: configure preset "gcc-release"
+
+Preset CMake variables:
+
+ CMAKE_BUILD_TYPE="RelWithDebInfo"
+ CMAKE_CXX_COMPILER="g++"
+ CMAKE_CXX_FLAGS="-O3"
+ CMAKE_CXX_STANDARD="17"
+
+-- The CXX compiler identification is GNU 13.2.0
+-- Detecting CXX compiler ABI info
+-- Detecting CXX compiler ABI info - done
+-- Check for working CXX compiler: /usr/bin/g++ - skipped
+-- Detecting CXX compile features
+-- Detecting CXX compile features - done
+-- Performing Test HAVE_DEDUCING_THIS
+-- Performing Test HAVE_DEDUCING_THIS - Failed
+-- The C compiler identification is GNU 13.2.0
+-- Detecting C compiler ABI info
+-- Detecting C compiler ABI info - done
+-- Check for working C compiler: /usr/bin/cc - skipped
+-- Detecting C compile features
+-- Detecting C compile features - done
+-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
+-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
+-- Found Threads: TRUE
+-- Configuring done (2.7s)
+-- Generating done (0.0s)
+-- Build files have been written to: /path/to/repo/.build/gcc-release
+
+Executing workflow step 2 of 3: build preset "gcc-release"
+
+[15/15] Linking CXX executable tests/beman/iterator_interface/beman.iterator_interface.tests
+
+Executing workflow step 3 of 3: test preset "gcc-release"
+
+Test project /path/to/repo/.build/gcc-release
+ Start 1: IteratorTest.TestGTest
+1/4 Test #1: IteratorTest.TestGTest ........... Passed 0.00 sec
+ Start 2: IteratorTest.TestRepeatedChars
+2/4 Test #2: IteratorTest.TestRepeatedChars ... Passed 0.00 sec
+ Start 3: IteratorTest.TestFilteredIter
+3/4 Test #3: IteratorTest.TestFilteredIter .... Passed 0.00 sec
+ Start 4: IteratorTest.OperatorArrow
+4/4 Test #4: IteratorTest.OperatorArrow ....... Passed 0.00 sec
+
+100% tests passed, 0 tests failed out of 4
+
+# Install build artifacts from `build` directory into `/opt/beman.iterator_interface` path.
+$ cmake --install .build/gcc-release --prefix /opt/beman.iterator_interface
+-- Install configuration: "RelWithDebInfo"
+-- Installing: /opt/beman.iterator_interface/lib/libbeman.iterator_interface.a
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/iterator_interface.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/iterator_interface_access.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/detail/stl_interfaces/config.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/detail/stl_interfaces/fwd.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/detail/stl_interfaces/iterator_interface.hpp
+-- Installing: /opt/beman.iterator_interface/bin/beman.iterator_interface.examples.filter_int_iterator
+-- Installing: /opt/beman.iterator_interface/bin/beman.iterator_interface.examples.repeated_chars_iterator
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/config.hpp
+
+
+# Check tree.
+$ tree /opt/beman.iterator_interface
+/opt/beman.iterator_interface
+├── bin
+│ ├── beman.iterator_interface.examples.filter_int_iterator
+│ └── beman.iterator_interface.examples.repeated_chars_iterator
+├── include
+│ └── beman
+│ └── iterator_interface
+│ ├── config.hpp
+│ ├── detail
+│ │ └── stl_interfaces
+│ │ ├── config.hpp
+│ │ ├── fwd.hpp
+│ │ └── iterator_interface.hpp
+│ ├── iterator_interface.hpp
+│ └── iterator_interface_access.hpp
+└── lib
+ └── libbeman.iterator_interface.a
+
+8 directories, 9 files
+
```
-This should build and run the tests with GCC 14 with the address and undefined behavior sanitizers enabled.
+
+
+#### Custom CMake Flows
+
+##### Default Build
+
+CI current build and test flows:
+```shell
+# Configure.
+$ cmake -G "Ninja Multi-Config" \
+ -DCMAKE_CONFIGURATION_TYPES="RelWithDebInfo;Asan" \
+ -DCMAKE_TOOLCHAIN_FILE=etc/clang-19-toolchain.cmake \
+ -B .build -S .
+
+# Build with config Asan.
+$ cmake --build .build --config Asan --target all -- -k 0
+# Build with config RelWithDebInfo.
+$ cmake --build .build --config RelWithDebInfo --target all -- -k 0
+
+# Run tests with config Asan..
+$ ctest --build-config Asan --output-on-failure --test-dir .build
+
+# Install library (default: config set to RelWithDebInfo).
+$ cmake --install .build/ --prefix /opt/beman.iterator_interface
+-- Install configuration: "RelWithDebInfo"
+-- Installing: /opt/beman.iterator_interface/lib/libbeman.iterator_interface.a
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/iterator_interface.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/iterator_interface_access.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/detail/stl_interfaces/config.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/detail/stl_interfaces/fwd.hpp
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/detail/stl_interfaces/iterator_interface.hpp
+-- Installing: /opt/beman.iterator_interface/bin/beman.iterator_interface.examples.filter_int_iterator
+-- Installing: /opt/beman.iterator_interface/bin/beman.iterator_interface.examples.repeated_chars_iterator
+-- Installing: /opt/beman.iterator_interface/include/beman/iterator_interface/config.hpp
+$ tree /opt/beman.iterator_interface
+/opt/beman.iterator_interface
+├── bin
+│ ├── beman.iterator_interface.examples.filter_int_iterator
+│ └── beman.iterator_interface.examples.repeated_chars_iterator
+├── include
+│ └── beman
+│ └── iterator_interface
+│ ├── config.hpp
+│ ├── detail
+│ │ └── stl_interfaces
+│ │ ├── config.hpp
+│ │ ├── fwd.hpp
+│ │ └── iterator_interface.hpp
+│ ├── iterator_interface.hpp
+│ └── iterator_interface_access.hpp
+└── lib
+ └── libbeman.iterator_interface.a
+
+8 directories, 9 files
+```
+
+
+ Build beman.iterator_interface and tests (verbose logs)
+
+```shell
+# Configure build: default build production code + tests (BEMAN_ITERATOR_INTERFACE_BUILD_TESTING=ON).
+$ cmake -G "Ninja Multi-Config" \
+ -DCMAKE_CONFIGURATION_TYPES="RelWithDebInfo;Asan" \
+ -DCMAKE_TOOLCHAIN_FILE=etc/clang-19-toolchain.cmake \
+ -B .build -S .
+-- The CXX compiler identification is Clang 19.0.0
+...
+-- Build files have been written to: /path/to/repo/.build
+
+# Build.
+$ cmake --build .build --config Asan --target all -- -k 0
+...
+[12/12] Linking CXX executable ... # Note: 12 targets here (including tests).
+
+# Run tests.
+$ ctest --build-config Asan --output-on-failure --test-dir .build
+Internal ctest changing into directory: /path/to/repo/.build
+Test project /path/to/repo/.build
+...
+100% tests passed, 0 tests failed out of 82
+
+Total Test time (real) = 0.67 sec
+```
+
+
+##### Skip Tests
+
+By default, we build and run tests. You can provide `-DBEMAN_ITERATOR_INTERFACE_BUILD_TESTING=OFF` and completely disable building tests:
+
+```shell
+# Configure.
+$ cmake -G "Ninja Multi-Config" \
+ -DCMAKE_CONFIGURATION_TYPES="RelWithDebInfo;Asan" \
+ -DCMAKE_TOOLCHAIN_FILE=etc/clang-19-toolchain.cmake \
+ -DBEMAN_ITERATOR_INTERFACE_BUILD_TESTING=OFF \
+ -B .build -S .
+```
-#### More complex cases
+##### Skip Examples
-The CMake preset system suffers from combinitorial explosion. There is a makefile in the root of the repository to aid in running more configurations.
+By default, we build and run tests. You can provide `-DBEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES=OFF` and completely disable building tests:
```shell
-make -k TOOLCHAIN=clang-18 CONFIG=Tsan VERBOSE=1
+# Configure.
+$ cmake -G "Ninja Multi-Config" \
+ -DCMAKE_CONFIGURATION_TYPES="RelWithDebInfo;Asan" \
+ -DCMAKE_TOOLCHAIN_FILE=etc/clang-19-toolchain.cmake \
+ -DBEMAN_ITERATOR_INTERFACE_BUILD_EXAMPLES=OFF \
+ -B .build -S .
```
-The makefile will use your system compiler, `c++`, if no toolchain name is provided, otherwise it will use the toolchain in the etc/ directory to perform the build. The Ninja multi config generator is used, with configurations for `RelWithDebugInfo`, `Debug`, `Tsan`, and `Asan` configured by default.
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 560a407..b6e94e6 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -4,7 +4,7 @@
# cmake-format: on
# List of all buildable examples.
-set(EXAMPLES sample)
+set(EXAMPLES filter_int_iterator repeated_chars_iterator)
foreach(example ${EXAMPLES})
# Add example executable.
diff --git a/examples/README.md b/examples/README.md
index dde22f4..b383872 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,22 +1,29 @@
+# Examples for beman.iterator_interface
+
-# beman.iterator_interfaces: Examples
+List of usage examples for `beman.iterator_interface`.
-List of usage examples for `beman.iterator_interfaces`.
+## Examples
-## Sample
+Check basic `beman.iterator_interface` library usages:
-TODO: update examples.
+* [P2727](https://wg21.link/P2727): local [./repeated_chars_iterator.cpp](./repeated_chars_iterator.cpp) or [repeated_chars_iterator.cpp@Compiler Explorer](https://godbolt.org/z/Yn9K15c9b)
+* [P2727](https://wg21.link/P2727): local [./filter_int_iterator.cpp](./filter_int_iterator.cpp) or [filter_int_iterator.cpp@Compiler Explorer](https://godbolt.org/z/q6933enqe)
-Check [sample](sample.cpp) for basic `beman.iterator_interfaces` library usage.
+## Local Build and Run
-Build and run instructions:
```shell
# build
-$ cmake --workflow --preset gcc-14
+$ cmake --workflow --preset gcc-debug
+
+# run repeated_chars_iterator.cpp
+$ .build/gcc-debug/examples/beman.iterator_interface.examples.repeated_chars_iterator
+foofoof
-# run sample
-$ .build/gcc-14/examples/RelWithDebInfo/sample
+# run filter_int_iterator.cpp
+$ .build/gcc-debug/examples/beman.iterator_interface.examples.filter_int_iterator
+2 4 10 200
```
diff --git a/examples/filter_int_iterator.cpp b/examples/filter_int_iterator.cpp
new file mode 100644
index 0000000..e51a0bc
--- /dev/null
+++ b/examples/filter_int_iterator.cpp
@@ -0,0 +1,71 @@
+// examples/filter_int_iterator.cpp -*-C++-*-
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// [P2727](https://wg21.link/P2727) example:
+// An iterator that allows filtering int elements of a sequence.
+
+#include
+
+#include
+#include
+#include
+
+// filtered_int_iterator uses std::iterator_interface to define a forward iterator
+// that iterates over a sequence of integers, skipping those that do not satisfy a predicate.
+template
+struct filtered_int_iterator
+ : beman::iterator_interface::ext_iterator_interface_compat,
+ std::forward_iterator_tag,
+ int> {
+ // Default constructor creates an end-of-range iterator.
+ filtered_int_iterator() : m_it_begin(nullptr) {}
+
+ // Constructor for the beginning of the sequence.
+ filtered_int_iterator(int* it_begin, int* it_end, Pred pred) : m_it_begin(it_begin), m_it_end(it_end), m_pred(std::move(pred)) {
+ m_it_begin = std::find_if(m_it_begin, m_it_end, m_pred);
+ }
+
+ // A forward iterator based on iterator_interface usually requires
+ // three user-defined operations. Since we are adapting an existing
+ // iterator (an int *), we only need to define this one. The others are
+ // implemented by iterator_interface, using the underlying int *.
+ filtered_int_iterator& operator++() {
+ m_it_begin = std::find_if(std::next(m_it_begin), m_it_end, m_pred);
+ return *this;
+ }
+
+ // It is really common for iterator adaptors to have a base() member
+ // function that returns the adapted iterator.
+ int* base() const { return m_it_begin; }
+
+ private:
+ // Provide access to base_reference.
+ friend beman::iterator_interface::iterator_interface_access;
+
+ // Provide access to base_reference.
+ constexpr auto base_reference() noexcept { return m_it_begin; }
+
+ // Start of the sequence of integers.
+ int* m_it_begin;
+
+ // End of the sequence of integers.
+ int* m_it_end;
+
+ // Predicate that determines which integers to skip.
+ Pred m_pred;
+};
+
+int main() {
+ // Create a filtered_int_iterator that iterates over the sequence {1, 2, 3, 4, 10, 11, 101, 200, 0},
+ // skipping odd numbers. 0 is not skipped, so it will be the last element in the sequence.
+ std::array a = {1, 2, 3, 4, 10, 11, 101, 200, 0};
+ filtered_int_iterator it{std::begin(a), std::end(a), [](int i) { return i % 2 == 0; }};
+
+ while (*it) { // Expected output at STDOUT:
+ std::cout << *it << " "; // 2 4 10 200 0
+ ++it;
+ }
+ std::cout << "\n";
+
+ return 0;
+}
diff --git a/examples/repeated_chars_iterator.cpp b/examples/repeated_chars_iterator.cpp
new file mode 100644
index 0000000..ab236f7
--- /dev/null
+++ b/examples/repeated_chars_iterator.cpp
@@ -0,0 +1,65 @@
+// examples/repeated_chars_iterator.cpp -*-C++-*-
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// [P2727](https://wg21.link/P2727) example:
+// An iterator that allows iterating over repetitions of a sequence of characters.
+
+#include
+
+#include
+#include
+#include
+#include
+
+// repeated_chars_iterator uses std::iterator_interface to define a random access iterator
+// that iterates over a sequence of characters repeated indefinitely.
+class repeated_chars_iterator
+ : public beman::iterator_interface::ext_iterator_interface_compat {
+public:
+ // Default constructor creates an end-of-range iterator.
+ constexpr repeated_chars_iterator() : m_it_begin(nullptr), m_fixed_size(0), m_pos(0) {}
+
+ // Constructor for the beginning of the sequence.
+ constexpr repeated_chars_iterator(const char* it_begin, difference_type size, difference_type n)
+ : m_it_begin(it_begin), m_fixed_size(size), m_pos(n) {}
+
+ // Random access iterator requirements:
+ constexpr auto operator*() const { return m_it_begin[m_pos % m_fixed_size]; }
+ constexpr repeated_chars_iterator& operator+=(std::ptrdiff_t i) {
+ m_pos += i;
+ return *this;
+ }
+ constexpr auto operator-(repeated_chars_iterator other) const { return m_pos - other.m_pos; }
+
+private:
+ // Start of the sequence of characters.
+ const char* m_it_begin;
+
+ // Number of characters in the sequence.
+ difference_type m_fixed_size;
+
+ // Current position in the sequence.
+ difference_type m_pos;
+};
+
+int main() {
+ // Create a repeated_chars_iterator that iterates over the sequence "foo" repeated indefinitely:
+ // "foofoofoofoofoofoo...". Will actually extract a prefix of the sequence and insert it into a std::string.
+ constexpr const std::string_view target = "foo";
+ constexpr const auto len = 7; // Number of extracted characters from the sequence.
+
+ // Create iterators that go over the sequence "foofoofoofoofoofoo...".
+ repeated_chars_iterator it_first(target.data(), target.size(), 0); // target.size() == 3 is the length of "foo", 0 is this iterator's position.
+ repeated_chars_iterator it_last(target.data(), target.size(), len); // Same as above, but now the iterator's position is 7.
+
+ std::string extracted_result;
+ std::copy(it_first, it_last, std::back_inserter(extracted_result));
+ assert(extracted_result.size() == len);
+ std::cout << extracted_result << "\n"; // Expected output at STDOUT: "foofoof"
+
+ return 0;
+}
+
diff --git a/examples/sample.cpp b/examples/sample.cpp
deleted file mode 100644
index 2e90a32..0000000
--- a/examples/sample.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// examples/sample.cpp -*-C++-*-
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include
-#include
-
-int main() {
-
- return 0;
-}