aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2020-03-01 12:19:49 +0100
committerFelix Morgner <felix.morgner@gmail.com>2020-03-01 12:19:49 +0100
commit1bd35044ee96e2bccb66749be5a48307c6e28218 (patch)
treea2e1b4760713a20ae63c3a72ae47425a71e7053c
parentf00fb5779dcf2443b74d114093afbbd2441523ad (diff)
parent8c5f53f0c3052cc30c2fe78feb1432b2a5c4e847 (diff)
downloadnewtype-master.tar.xz
newtype-master.zip
newtype: release version 1.1.0v1.1.0master
-rw-r--r--.readthedocs.yml4
-rw-r--r--.travis.yml31
-rw-r--r--.vscode/settings.json72
-rw-r--r--CMakeLists.txt119
-rw-r--r--LICENSE2
-rw-r--r--conanfile.py21
-rw-r--r--doc/.gitignore2
-rw-r--r--doc/Pipfile12
-rw-r--r--doc/Pipfile.lock217
-rw-r--r--doc/requirements.txt1
-rw-r--r--doc/src/conf.py6
-rw-r--r--doc/src/index.rst440
-rw-r--r--doc8.ini2
-rw-r--r--include/newtype/derivable.hpp58
-rw-r--r--include/newtype/derivation_clause.hpp45
-rw-r--r--include/newtype/deriving.hpp3
-rw-r--r--include/newtype/impl/new_type_iterator_types.hpp66
-rw-r--r--include/newtype/impl/type_traits_extensions.hpp923
-rw-r--r--include/newtype/new_type.hpp527
-rw-r--r--include/newtype/version.hpp6
-rw-r--r--test/include/iterable_suite.hpp11
-rw-r--r--test/src/driver.cpp2
-rw-r--r--test/src/iterable_suite.cpp719
-rw-r--r--test_package/.gitignore1
-rw-r--r--test_package/CMakeLists.txt10
-rw-r--r--test_package/conanfile.py17
-rw-r--r--test_package/main.cpp11
27 files changed, 2012 insertions, 1316 deletions
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 6514c09..6dd17ed 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -8,7 +8,9 @@ formats:
python:
version: 3.7
+ install:
+ - requirements: doc/requirements.txt
sphinx:
builder: singlehtml
- configuration: doc/src/conf.py \ No newline at end of file
+ configuration: doc/src/conf.py
diff --git a/.travis.yml b/.travis.yml
index 5091396..f523e70 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,26 +6,37 @@ dist: bionic
addons:
apt:
sources:
- - sourceline: "ppa:ubuntu-toolchain-r/test"
- packages: ['g++-9']
+ - sourceline: 'ppa:ubuntu-toolchain-r/test'
+ - sourceline: 'deb https://apt.kitware.com/ubuntu/ bionic main'
+ key_url: 'https://apt.kitware.com/keys/kitware-archive-latest.asc'
+ packages:
+ - g++-9
+ - cmake
+ - libperlio-gzip-perl
+ - libjson-perl
compiler:
- gcc
-env:
- - CXX=g++-9
-
cache:
directories:
- $HOME/.conan/data
+before_install:
+ - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 20
+ - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 20
+ - sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-9 20
+ - sudo update-alternatives --config gcc
+ - sudo update-alternatives --config g++
+ - sudo update-alternatives --config gcov
+
install:
- pip install conan
- conan user
+ - git clone git://github.com/linux-test-project/lcov.git
+ - cd lcov && sudo make install
+ - cd ..
script:
- - mkdir -p build
- - cd build
- - cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=ON ..
- - cmake --build . --target all
- - ctest
+ - /usr/bin/cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=YES -DRUN_TESTS_AFTER_BUILD=YES -DENABLE_CODE_COVERAGE=YES -DPRINT_COVERAGE_REPORT=YES
+ - /usr/bin/cmake --build build --target all --parallel $(nproc)
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8caed1c..d237db4 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,75 +1,15 @@
{
- "files.associations": {
- ".clang-format": "yaml",
- "array": "cpp",
- "chrono": "cpp",
- "functional": "cpp",
- "istream": "cpp",
- "ostream": "cpp",
- "ratio": "cpp",
- "tuple": "cpp",
- "type_traits": "cpp",
- "utility": "cpp",
- "variant": "cpp",
- "atomic": "cpp",
- "hash_map": "cpp",
- "bit": "cpp",
- "*.tcc": "cpp",
- "cctype": "cpp",
- "clocale": "cpp",
- "cmath": "cpp",
- "condition_variable": "cpp",
- "cstdarg": "cpp",
- "cstddef": "cpp",
- "cstdint": "cpp",
- "cstdio": "cpp",
- "cstdlib": "cpp",
- "cstring": "cpp",
- "ctime": "cpp",
- "cwchar": "cpp",
- "cwctype": "cpp",
- "deque": "cpp",
- "list": "cpp",
- "map": "cpp",
- "set": "cpp",
- "unordered_map": "cpp",
- "vector": "cpp",
- "exception": "cpp",
- "algorithm": "cpp",
- "iterator": "cpp",
- "memory": "cpp",
- "memory_resource": "cpp",
- "numeric": "cpp",
- "optional": "cpp",
- "random": "cpp",
- "string": "cpp",
- "string_view": "cpp",
- "system_error": "cpp",
- "fstream": "cpp",
- "initializer_list": "cpp",
- "iomanip": "cpp",
- "iosfwd": "cpp",
- "iostream": "cpp",
- "limits": "cpp",
- "mutex": "cpp",
- "new": "cpp",
- "sstream": "cpp",
- "stdexcept": "cpp",
- "streambuf": "cpp",
- "thread": "cpp",
- "cfenv": "cpp",
- "cinttypes": "cpp",
- "typeinfo": "cpp",
- "valarray": "cpp",
- "*.ipp": "cpp",
- "bitset": "cpp",
- "netfwd": "cpp"
- },
+ // CMake Configuration
"cmake.configureArguments": "-DCMAKE_EXPORT_COMPILE_COMMANDS=YES",
"cmake.cpptools.intelliSenseMode": "gcc-x64",
"cmake.cpptools.guessSourceFileConfigurations": true,
+
+ // C++ Configuration
"[cpp]": {
"editor.formatOnSave": true
},
+ "C_Cpp.autoAddFileAssociations": false,
+
+ // RST Configuration
"restructuredtext.confPath": "${workspaceFolder}/doc/src"
} \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ba03c5f..3c29a76 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,19 +1,21 @@
cmake_minimum_required(VERSION "3.9.0")
project("newtype"
- VERSION "1.0.2"
+ VERSION "1.1.0"
LANGUAGES CXX
DESCRIPTION "A library of types and functions to create strong type aliases"
)
-set(CMAKE_CXX_STANDARD "20")
-set(CMAKE_CXX_STANDARD_REQUIRED YES)
-set(CMAKE_CXX_EXTENSIONS OFF)
-set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
-
-include("CTest")
include("CMakePackageConfigHelpers")
+# Project Options
+
+option(RUN_TESTS_AFTER_BUILD "Automatically run the unit tests after building" ON)
+option(BUILD_TESTING "Build the unit tests" ON)
+option(ENABLE_CODE_COVERAGE "Enable building support for code coverage report generation" ON)
+option(PRINT_COVERAGE_REPORT "Print a coverage report after running the unit tests" ON)
+option(GENERATE_COVERAGE_REPORT "Generate an HTML coverage report after running the unit tests" OFF)
+
# 'newtype' library
add_library("${PROJECT_NAME}" INTERFACE)
@@ -23,6 +25,10 @@ target_include_directories("${PROJECT_NAME}" INTERFACE
$<INSTALL_INTERFACE:include>
)
+target_compile_features("${PROJECT_NAME}" INTERFACE
+ "cxx_std_20"
+)
+
install(TARGETS "${PROJECT_NAME}"
EXPORT "${PROJECT_NAME}Targets"
PUBLIC_HEADER DESTINATION "include"
@@ -35,12 +41,31 @@ install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/"
# 'newtype' tests
if(BUILD_TESTING)
+ enable_testing()
+
+ if(PRINT_COVERAGE_REPORT)
+ find_program(LCOV_EXE NAMES "lcov")
+ mark_as_advanced(LCOV_EXE)
+ if(NOT LCOV_EXE)
+ message(FATAL_ERROR "lcov is required to generate code coverage reports")
+ endif()
+ endif()
+
+ if(GENERATE_COVERAGE_REPORT)
+ find_program(GENHTML_EXE NAMES "genhtml")
+ mark_as_advanced(GENHTML_EXE)
+ if(NOT GENHTML_EXE)
+ message(FATAL_ERROR "genhtml is required to generate code coverage reports")
+ endif()
+ endif()
+
include("${PROJECT_SOURCE_DIR}/cmake/Modules/DiscoverTests.cmake")
include("${PROJECT_SOURCE_DIR}/cmake/Modules/Conan.cmake")
conan_check(REQUIRED)
conan_add_remote(NAME "fmorgner-public" URL "https://api.bintray.com/conan/fmorgner/conan-public")
conan_cmake_run(CONANFILE "conanfile.py"
+ OUTPUT_QUIET
BASIC_SETUP
CMAKE_TARGETS
BUILD "missing"
@@ -56,6 +81,7 @@ if(BUILD_TESTING)
"${PROJECT_SOURCE_DIR}/test/src/equality_comparison_suite.cpp"
"${PROJECT_SOURCE_DIR}/test/src/hash_suite.cpp"
"${PROJECT_SOURCE_DIR}/test/src/io_operators_suite.cpp"
+ "${PROJECT_SOURCE_DIR}/test/src/iterable_suite.cpp"
"${PROJECT_SOURCE_DIR}/test/src/new_type_constructor_suite.cpp"
"${PROJECT_SOURCE_DIR}/test/src/relational_operators_suite.cpp"
)
@@ -75,16 +101,78 @@ if(BUILD_TESTING)
"-Wextra"
"-Werror"
"-pedantic-errors"
+ $<$<BOOL:${ENABLE_CODE_COVERAGE}>:--coverage>
)
- discover_tests(TARGET "${PROJECT_NAME}_tests")
+ target_link_options("${PROJECT_NAME}_tests" PRIVATE
+ $<$<BOOL:${ENABLE_CODE_COVERAGE}>:--coverage>
+ )
- add_custom_target("run_all_tests"
- COMMAND ${CMAKE_CTEST_COMMAND} "--output-on-failure"
- WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
- DEPENDS "newtype_tests"
- COMMENT "Running unit tests"
+ set_target_properties("${PROJECT_NAME}_tests" PROPERTIES
+ CXX_EXTENSIONS OFF
)
+
+ discover_tests(TARGET "${PROJECT_NAME}_tests")
+
+ if(RUN_TESTS_AFTER_BUILD)
+ add_custom_command(TARGET "${PROJECT_NAME}_tests"
+ POST_BUILD
+ DEPENDS "${PROJECT_NAME}_tests"
+ COMMAND "${CMAKE_CTEST_COMMAND}"
+ ARGS
+ "--output-on-failure"
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
+ COMMENT "Running unit tests"
+ )
+ endif()
+
+ if(ENABLE_CODE_COVERAGE AND RUN_TESTS_AFTER_BUILD)
+ add_custom_command(TARGET "${PROJECT_NAME}_tests"
+ POST_BUILD
+ BYPRODUCTS "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.coverage.info"
+ COMMAND "${LCOV_EXE}"
+ ARGS
+ "--capture"
+ "--base-directory" "${PROJECT_SOURCE_DIR}"
+ "--directory" "${PROJECT_BINARY_DIR}"
+ "--output-file" "${PROJECT_NAME}.coverage.info"
+ "--no-external"
+ "--exclude" "${PROJECT_SOURCE_DIR}/test/\\*"
+ ">/dev/null"
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
+ COMMENT "Capturing code coverage data"
+ )
+
+ if(PRINT_COVERAGE_REPORT)
+ add_custom_command(TARGET "${PROJECT_NAME}_tests"
+ POST_BUILD
+ COMMAND "${LCOV_EXE}"
+ ARGS
+ "--list"
+ "${PROJECT_NAME}.coverage.info"
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
+ COMMENT "Printing code coverage report"
+ )
+ endif()
+
+ if(GENERATE_COVERAGE_REPORT)
+ add_custom_command(TARGET "${PROJECT_NAME}_tests"
+ POST_BUILD
+ BYPRODUCTS "${PROJECT_BINARY_DIR}/coverage-report/index.html"
+ COMMAND "${GENHTML_EXE}"
+ ARGS
+ "--demangle-cpp"
+ "--highlight"
+ "--missed"
+ "--show-details"
+ "--output" "coverage-report"
+ "${PROJECT_NAME}.coverage.info"
+ ">/dev/null"
+ WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
+ COMMENT "Generating code coverage report"
+ )
+ endif()
+ endif()
endif()
# 'newtype' docs
@@ -93,13 +181,16 @@ option(BUILD_DOCS "Build the library documentation" OFF)
if(BUILD_DOCS)
find_program(PIPENV_EXE NAMES "pipenv3" "pipenv")
+ mark_as_advanced(PIPENV_EXE)
if(NOT PIPENV_EXE)
message(FATAL_ERROR "Could not find pipenv")
endif()
- execute_process(COMMAND "${PIPENV_EXE}" "install"
+ message(STATUS "Installing documentation dependencies via pipenv")
+ execute_process(COMMAND "${PIPENV_EXE}" "install" "-r" "requirements.txt"
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/doc"
OUTPUT_QUIET
+ ERROR_QUIET
)
set(DOC_SOURCES
diff --git a/LICENSE b/LICENSE
index 3959b78..18858da 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2019, Felix Morgner <felix.morgner@gmail.com>, all rights reserved
+Copyright (c) 2020, Felix Morgner <felix.morgner@gmail.com>, all rights reserved
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
diff --git a/conanfile.py b/conanfile.py
index 8b3e147..000831e 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -4,11 +4,11 @@ from conans import ConanFile, CMake
from conans.tools import load
-def get_version():
+def read_project_property(property):
try:
- content = load("CMakeLists.txt")
- version = re.search("project\(\"newtype\"\s*VERSION \"(.*)\"", content).group(1)
- return version.strip()
+ cmake_lists = load("CMakeLists.txt")
+ value = re.search(r"project\(.*{} \"(.*?)\"".format(property), cmake_lists, re.S).group(1)
+ return value.strip()
except:
return None
@@ -20,11 +20,11 @@ class NewtypeConan(ConanFile):
"url": "https://github.com/fmorgner/newtype.git",
"revision": "auto",
}
- settings = ("compiler",)
- version = get_version()
+ settings = None
+ version = read_project_property("VERSION")
license = "BSD-3-Clause"
url = "https://github.com/fmorgner/newtype"
- description = "A library of types and functions to create strong type aliases"
+ description = read_project_property("DESCRIPTION")
generators = "cmake"
build_requires = (
"CUTE/2.2.6@fmorgner/stable",
@@ -34,18 +34,17 @@ class NewtypeConan(ConanFile):
def _configure_cmake(self):
cmake = CMake(self)
cmake.definitions["BUILD_TESTING"] = True
+ cmake.definitions["RUN_TESTS_AFTER_BUILD"] = True
cmake.configure()
return cmake
def build(self):
cmake = self._configure_cmake()
cmake.build()
- cmake.test()
def package(self):
cmake = self._configure_cmake()
cmake.install()
- def package_info(self):
- if self.settings.compiler in ["gcc"]:
- self.cpp_info.cxxflags.append("-std=c++2a") \ No newline at end of file
+ def package_id(self):
+ self.info.header_only() \ No newline at end of file
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..ee826c1
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,2 @@
+Pipfile
+Pipfile.lock
diff --git a/doc/Pipfile b/doc/Pipfile
deleted file mode 100644
index 83bd30b..0000000
--- a/doc/Pipfile
+++ /dev/null
@@ -1,12 +0,0 @@
-[[source]]
-name = "pypi"
-url = "https://pypi.org/simple"
-verify_ssl = true
-
-[dev-packages]
-
-[packages]
-sphinx = "*"
-
-[requires]
-python_version = "3"
diff --git a/doc/Pipfile.lock b/doc/Pipfile.lock
deleted file mode 100644
index f23f13b..0000000
--- a/doc/Pipfile.lock
+++ /dev/null
@@ -1,217 +0,0 @@
-{
- "_meta": {
- "hash": {
- "sha256": "776b8d64e53c6045ac2d3198bb1516e980e399d054e903e0769d4e6c13350e50"
- },
- "pipfile-spec": 6,
- "requires": {
- "python_version": "3"
- },
- "sources": [
- {
- "name": "pypi",
- "url": "https://pypi.org/simple",
- "verify_ssl": true
- }
- ]
- },
- "default": {
- "alabaster": {
- "hashes": [
- "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359",
- "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"
- ],
- "version": "==0.7.12"
- },
- "babel": {
- "hashes": [
- "sha256:af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab",
- "sha256:e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"
- ],
- "version": "==2.7.0"
- },
- "certifi": {
- "hashes": [
- "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
- "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
- ],
- "version": "==2019.11.28"
- },
- "chardet": {
- "hashes": [
- "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
- "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
- ],
- "version": "==3.0.4"
- },
- "docutils": {
- "hashes": [
- "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0",
- "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827",
- "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99"
- ],
- "version": "==0.15.2"
- },
- "idna": {
- "hashes": [
- "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
- "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
- ],
- "version": "==2.8"
- },
- "imagesize": {
- "hashes": [
- "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8",
- "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"
- ],
- "version": "==1.1.0"
- },
- "jinja2": {
- "hashes": [
- "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f",
- "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"
- ],
- "version": "==2.10.3"
- },
- "markupsafe": {
- "hashes": [
- "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
- "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
- "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
- "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
- "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
- "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
- "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
- "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
- "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
- "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
- "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
- "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
- "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
- "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
- "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
- "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
- "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
- "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
- "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
- "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
- "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
- "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
- "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
- "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
- "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
- "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
- "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
- "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
- ],
- "version": "==1.1.1"
- },
- "packaging": {
- "hashes": [
- "sha256:28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47",
- "sha256:d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108"
- ],
- "version": "==19.2"
- },
- "pygments": {
- "hashes": [
- "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b",
- "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe"
- ],
- "version": "==2.5.2"
- },
- "pyparsing": {
- "hashes": [
- "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
- "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
- ],
- "version": "==2.4.6"
- },
- "pytz": {
- "hashes": [
- "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
- "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
- ],
- "version": "==2019.3"
- },
- "requests": {
- "hashes": [
- "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
- "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
- ],
- "version": "==2.22.0"
- },
- "six": {
- "hashes": [
- "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
- "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
- ],
- "version": "==1.13.0"
- },
- "snowballstemmer": {
- "hashes": [
- "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0",
- "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"
- ],
- "version": "==2.0.0"
- },
- "sphinx": {
- "hashes": [
- "sha256:298537cb3234578b2d954ff18c5608468229e116a9757af3b831c2b2b4819159",
- "sha256:e6e766b74f85f37a5f3e0773a1e1be8db3fcb799deb58ca6d18b70b0b44542a5"
- ],
- "index": "pypi",
- "version": "==2.3.1"
- },
- "sphinxcontrib-applehelp": {
- "hashes": [
- "sha256:edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897",
- "sha256:fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d"
- ],
- "version": "==1.0.1"
- },
- "sphinxcontrib-devhelp": {
- "hashes": [
- "sha256:6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34",
- "sha256:9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981"
- ],
- "version": "==1.0.1"
- },
- "sphinxcontrib-htmlhelp": {
- "hashes": [
- "sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422",
- "sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7"
- ],
- "version": "==1.0.2"
- },
- "sphinxcontrib-jsmath": {
- "hashes": [
- "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178",
- "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"
- ],
- "version": "==1.0.1"
- },
- "sphinxcontrib-qthelp": {
- "hashes": [
- "sha256:513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20",
- "sha256:79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f"
- ],
- "version": "==1.0.2"
- },
- "sphinxcontrib-serializinghtml": {
- "hashes": [
- "sha256:c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227",
- "sha256:db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768"
- ],
- "version": "==1.1.3"
- },
- "urllib3": {
- "hashes": [
- "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293",
- "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
- ],
- "version": "==1.25.7"
- }
- },
- "develop": {}
-}
diff --git a/doc/requirements.txt b/doc/requirements.txt
new file mode 100644
index 0000000..b80a564
--- /dev/null
+++ b/doc/requirements.txt
@@ -0,0 +1 @@
+sphinx==2.4.2
diff --git a/doc/src/conf.py b/doc/src/conf.py
index 437d275..1337ce3 100644
--- a/doc/src/conf.py
+++ b/doc/src/conf.py
@@ -6,10 +6,10 @@ import os
# -- Project information -----------------------------------------------------
project = 'newtype'
-copyright = '2019, Felix Morgner'
+copyright = '2020, Felix Morgner'
author = 'Felix Morgner'
-version = '1.0'
-release = '1.0.0'
+version = '1.1'
+release = '1.1.0'
# -- General configuration ---------------------------------------------------
diff --git a/doc/src/index.rst b/doc/src/index.rst
index 49db3b6..290f17e 100644
--- a/doc/src/index.rst
+++ b/doc/src/index.rst
@@ -28,7 +28,7 @@ In it, :cpp:class:`new_type` is used to create thre new strong aliases :literal:
.. literalinclude:: ../../examples/src/basic_usage.cpp
:language: c++
:linenos:
- :name: new-type-usage-basic
+ :name: new-type-usage-basic
:caption: Basic usage of :cpp:class:`new_type`
However, using :cpp:class:`new_type` in this fashion seem quite cumbersome.
@@ -76,7 +76,7 @@ Class template :cpp:class:`new_type`
:tparam BaseType: |BaseTypeDoc|
:tparam TagType: |TagTypeDoc|
:tparam DerivationClause: |DerivationClauseDoc|
-
+
.. versionadded:: 1.0.0
**Member Type Aliases**
@@ -87,6 +87,30 @@ Class template :cpp:class:`new_type`
.. cpp:type:: derivation_clause_type = decltype(DerivationClause)
+ .. cpp:type:: iterator = typename BaseType::iterator
+
+ :enablement: This type alias shall be defined iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` has a member type :cpp:type:`iterator <new_type::base_type::iterator>` and the :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable`.
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:type:: const_iterator = typename BaseType::const_iterator
+
+ :enablement: This type alias shall be defined iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` has a member type :cpp:type:`const_iterator <new_type::base_type::const_iterator>` and the :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable`.
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:type:: reverse_iterator = typename BaseType::reverse_iterator
+
+ :enablement: This type alias shall be defined iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` has a member type :cpp:type:`reverse_iterator <new_type::base_type::reverse_iterator>` and the :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable`.
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:type:: const_reverse_iterator = typename BaseType::const_reverse_iterator
+
+ :enablement: This type alias shall be defined iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` has a member type :cpp:type:`const_reverse_iterator <new_type::base_type::const_reverse_iterator>` and the :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable`.
+
+ .. versionadded:: 1.1.0
+
**Static Data Members**
.. cpp:var:: static derivation_clause_type constexpr derivation_clause = DerivationClause
@@ -168,14 +192,14 @@ Class template :cpp:class:`new_type`
.. cpp:function:: constexpr BaseType decay() const
- Retrieve the object contained by this :cpp:class:`new_type` object
+ Retrieve a copy of the object contained by this :cpp:class:`new_type` object
:throws: Any exception thrown by the copy-constructor of this :cpp:class:`new_type`'s :cpp:type:`base_type`.
This operator shall be noexcept iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` is *nothrow copy-constructible*.
.. cpp:function:: constexpr operator BaseType() const
- Retrieve the object contained by this :cpp:class:`new_type` object
+ Retrieve a copy of the object contained by this :cpp:class:`new_type` object
:throws: Any exception thrown by the copy-constructor of this :cpp:class:`new_type`'s :cpp:type:`base_type`.
This operator shall be noexcept iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` is *nothrow copy-constructible*.
@@ -195,6 +219,140 @@ Class template :cpp:class:`new_type`
:enablement: This operator shall be available iff. this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Indirection`
+ **Iterators**
+
+ .. cpp:function:: constexpr iterator begin()
+
+ Get an iterator to the beginning of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`begin() <new_type::base_type::begin()>` that returns an instance of type :cpp:type:`iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator begin() const
+
+ Get a constant iterator to the beginning of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`begin() const <new_type::base_type::begin()>` that returns an instance of type :cpp:type:`const_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator cbegin() const
+
+ Get a constant iterator to the beginning of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`cbegin() const <new_type::base_type::cbegin()>` that returns an instance of type :cpp:type:`const_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator rbegin()
+
+ Get a reverse iterator to the beginning of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`rbegin() <new_type::base_type::rbegin()>` that returns an instance of type :cpp:type:`reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator rbegin() const
+
+ Get a constant reverse iterator to the beginning of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`rbegin() const <new_type::base_type::rbegin()>` that returns an instance of type :cpp:type:`const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator crbegin() const
+
+ Get a constant reverse iterator to the beginning of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`crbegin() const <new_type::base_type::crbegin()>` that returns an instance of type :cpp:type:`const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator end()
+
+ Get an iterator beyond the end of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`end() <new_type::base_type::end()>` that returns an instance of type :cpp:type:`iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator end() const
+
+ Get a constant iterator beyond the end of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`end() const <new_type::base_type::end()>` that returns an instance of type :cpp:type:`const_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator cend() const
+
+ Get a constant iterator beyond the end of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`cend() const <new_type::base_type::cend()>` that returns an instance of type :cpp:type:`const_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator rend()
+
+ Get a reverse iterator beyond the end of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`rend() <new_type::base_type::rend()>` that returns an instance of type :cpp:type:`reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator rend() const
+
+ Get a constant reverse iterator beyond the end of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`rend() const <new_type::base_type::rend()>` that returns an instance of type :cpp:type:`const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+ .. cpp:function:: constexpr iterator crend() const
+
+ Get a constant reverse iterator beyond the end of the object contained by this :cpp:class:`new_type`
+
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and
+ b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`crend() const <new_type::base_type::crend()>` that returns an instance of type :cpp:type:`const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
:literal:`namespace`-level functions and function templates
-----------------------------------------------------------
@@ -233,7 +391,7 @@ Equality Comparison Operators
:returns: The value returned by the comparison of object contained by :literal:`lhs` with an object of the :cpp:type:`base type <new_type::base_type>`.
:throws: Any exception thrown by the comparison of object contained by :literal:`lhs` with an object of the :cpp:type:`base type <new_type::base_type>`. This operator shall be noexcept iff. :cpp:type:`new_type::base_type` is *nothrow equals-comparable*.
:enablement: This operator shall be available iff.
-
+
a. :cpp:type:`new_type::base_type` supports comparison using :literal:`==` and
b. the :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`EqBase`
@@ -252,7 +410,7 @@ Equality Comparison Operators
:returns: The value returned by the comparison of an object of :cpp:type:`base type <new_type::base_type>` with the object contained by :literal:`rhs`.
:throws: Any exception thrown by the comparison of an object of :cpp:type:`base type <new_type::base_type>` with the object contained by :literal:`rhs`. This operator shall be noexcept iff. :cpp:type:`new_type::base_type` is *nothrow equals-comparable*.
:enablement: This operator shall be available iff.
-
+
a. :cpp:type:`new_type::base_type` supports comparison using :literal:`==` and
b. the :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`EqBase`
@@ -308,7 +466,7 @@ Equality Comparison Operators
:returns: The value returned by the comparison of an object of :cpp:type:`base type <new_type::base_type>` with the object contained by :literal:`rhs`.
:throws: Any exception thrown by the comparison of an object of :cpp:type:`base type <new_type::base_type>` with the object contained by :literal:`rhs`. This operator shall be noexcept iff. :cpp:type:`new_type::base_type` is *nothrow not-equals-comparable*.
:enablement: This operator shall be available iff.
-
+
a. :cpp:type:`new_type::base_type` supports comparison using :literal:`!=` and
b. the :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`EqBase`
@@ -407,6 +565,8 @@ Stream I/O Operators
typename StreamTraits> \
std::basic_ostream<CharType, StreamTraits> & operator<<(std::basic_ostream<CharType, StreamTraits> & out, new_type<BaseType, TagType, DerivationClause> const & value)
+ Write an instance of :cpp:class:`new_type\<BaseType, TagType, DerivationClause>` to a standard :cpp:type:`ostream <std::ostream>`.
+
:tparam BaseType: |BaseTypeDoc|
:tparam TagType: |TagTypeDoc|
:tparam DerivationClause: |DerivationClauseDoc|
@@ -431,6 +591,8 @@ Stream I/O Operators
typename StreamTraits> \
std::basic_istream<CharType, StreamTraits> & operator>>(std::basic_istream<CharType, StreamTraits> & in, new_type<BaseType, TagType, DerivationClause> & value)
+ Read an instance of :cpp:class:`new_type\<BaseType, TagType, DerivationClause>` from a standard :cpp:type:`istream <std::istream>`.
+
:tparam BaseType: |BaseTypeDoc|
:tparam TagType: |TagTypeDoc|
:tparam DerivationClause: |DerivationClauseDoc|
@@ -464,7 +626,7 @@ Arithmetic Operators
:returns: A new instance of :cpp:class:`new_type\<BaseType, TagType, DerivationClause>` containing the result of applying :literal:`+` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the addition operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow addable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -488,7 +650,7 @@ Arithmetic Operators
:returns: A reference to the first argument containing the value modified by applying :literal:`+=` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the addition-assignment operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow add-assignable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -512,7 +674,7 @@ Arithmetic Operators
:returns: A new instance of :cpp:class:`new_type\<BaseType, TagType, DerivationClause>` containing the result of applying :literal:`-` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the subtraction operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow subtractable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -536,7 +698,7 @@ Arithmetic Operators
:returns: A reference to the first argument containing the value modified by applying :literal:`-=` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the subtraction-assignment operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow subtract-assignable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -560,7 +722,7 @@ Arithmetic Operators
:returns: A new instance of :cpp:class:`new_type\<BaseType, TagType, DerivationClause>` containing the result of applying :literal:`*` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the multiplication operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow multipliable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -584,7 +746,7 @@ Arithmetic Operators
:returns: A reference to the first argument containing the value modified by applying :literal:`*=` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the multiplication-assignment operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow multiply-assignable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -608,7 +770,7 @@ Arithmetic Operators
:returns: A new instance of :cpp:class:`new_type\<BaseType, TagType, DerivationClause>` containing the result of applying :literal:`/` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the division operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow dividable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -631,7 +793,7 @@ Arithmetic Operators
:returns: A reference to the first argument containing the value modified by applying :literal:`/=` to the objects contained by :literal:`lhs` and :literal:`rhs`.
:throws: Any exception thrown by the division-assignment operator of the objects contained by :literal:`lhs` and :literal:`rhs`.
This operator shall be noexcept iff.
-
+
a. :cpp:type:`new_type::base_type` is *nothrow divide-assignable* and
b. :cpp:type:`new_type::base_type` is *nothrow copy-constructible*
@@ -642,6 +804,225 @@ Arithmetic Operators
.. versionadded:: 1.0.0
+Iterators
+~~~~~~~~~
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::iterator begin(new_type<BaseType, TagType, DerivationClause> & obj)
+
+ Get an iterator to the beginning of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator to the begining of the object of contained by :literal:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`begin(BaseType &)` that returns an instance of type :cpp:type:`new_type::iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_iterator begin(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant iterator to the beginning of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator to the begining of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`begin(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_iterator cbegin(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant iterator to the beginning of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator to the begining of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`cbegin(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::reverse_iterator rbegin(new_type<BaseType, TagType, DerivationClause> & obj)
+
+ Get a reverse iterator to the beginning of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator to the begining of the object of contained by :literal:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`rbegin(BaseType &)` that returns an instance of type :cpp:type:`new_type::reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator rbegin(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant reverse iterator to the beginning of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator to the begining of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`rbegin(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator crbegin(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant reverse iterator to the beginning of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator to the begining of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`crbegin(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::iterator end(new_type<BaseType, TagType, DerivationClause> & obj)
+
+ Get an iterator beyond the end of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator beyond the end of the object of contained by :literal:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`end(BaseType &)` that returns an instance of type :cpp:type:`new_type::iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_iterator end(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant iterator beyond the end of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator beyond the end of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`end(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_iterator cend(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant iterator beyond the end of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator beyond the end of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`cend(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::reverse_iterator rend(new_type<BaseType, TagType, DerivationClause> & obj)
+
+ Get a reverse iterator beyond the end of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator beyond the end of the object of contained by :literal:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`rend(BaseType &)` that returns an instance of type :cpp:type:`new_type::reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator rend(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant reverse iterator beyond the end of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator beyond the end of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`rend(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
+.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \
+ constexpr new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator crend(new_type<BaseType, TagType, DerivationClause> const & obj)
+
+ Get a constant reverse iterator beyond the end of the object contained by an instance of :cpp:class:`new_type`
+
+ :tparam BaseType: |BaseTypeDoc|
+ :tparam TagType: |TagTypeDoc|
+ :tparam DerivationClause: |DerivationClauseDoc|
+ :param obj: The object to retrieve the iterator from
+ :returns: An iterator beyond the end of the object of contained by :cpp:var:`obj`.
+ :throws: Any exception
+ :enablement: This function shall be available iff.
+
+ a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and
+ b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`crend(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_reverse_iterator`
+
+ .. versionadded:: 1.1.0
+
:cpp:class:`std::hash` Support
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -654,13 +1035,15 @@ Arithmetic Operators
:tparam TagType: |TagTypeDoc|
:tparam DerivationClause: |DerivationClauseDoc|
+ Hash an instance of :cpp:class:`new_type` using the hash implementation of the :cpp:type:`base type <BaseType>`.
+
.. cpp:function:: constexpr std::size operator()(nt::new_type<BaseType, TagType, DerivationClause> const & value) const
:param value: A :cpp:class:`nt::new_type` value to be hashed
:returns: The result of applying :cpp:class:`std::hash` to the object contained by :literal:`value`
:throws: Any exception thrown by the call operator of the specialization of :cpp:class`std::hash` for the type of the object contained by :literal:`value`.
:enablement: This operator shall be available iff.
-
+
a. :cpp:type:`nt::new_type::base_type` is hashable and
b. the :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Hash <nt::Hash>`.
@@ -691,7 +1074,7 @@ Standard derivation tags
.. cpp:var:: auto constexpr Arithmetic = derivable<class arithmetic_tag>{}
This tag enables the derivation of the following arithmetic operators:
-
+
* :cpp:func:`operator+(new_type const &, new_type const &) <template\<typename BaseType, typename TagType, auto DerivationClause> constexpr new_type<BaseType, TagType, DerivationClause> operator+(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs)>`
* :cpp:func:`operator-(new_type const &, new_type const &) <template\<typename BaseType, typename TagType, auto DerivationClause> constexpr new_type<BaseType, TagType, DerivationClause> operator-(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs)>`
* :cpp:func:`operator*(new_type const &, new_type const &) <template\<typename BaseType, typename TagType, auto DerivationClause> constexpr new_type<BaseType, TagType, DerivationClause> operator*(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs)>`
@@ -731,15 +1114,18 @@ Standard derivation tags
.. cpp:var:: auto constexpr Indirection = derivable<class indirection_tag>{}
- .. .. cpp:function:: constexpr BaseType operator->() noexcept
+ This tag enables the derivation of the "member access through pointer" operator :cpp:func:`operator->() <constexpr BaseType new_type::operator->()()>` (both in :literal:`const` and non-:literal:`const` variants).
- .. **enablement:** This operator shall be available iff. this :cpp:class:`new_type`'s :cpp:var:`derivation_clause` contains :cpp:var:`Indirection`
+ .. versionadded:: 1.0.0
- .. .. cpp:function:: constexpr BaseType const * operator->() const noexcept
+.. cpp:var:: auto constexpr Iterable = derivable<class iterable_tag>{}
- This tag enables the derivation of the "member access through pointer" operator :cpp:func:`operator->() <constexpr BaseType new_type::operator->()()>` (both in :literal:`const` and non-:literal:`const` variants).
+ This tag enables the derivation of the following "standard iterator functions":
- .. versionadded:: 1.0.0
+ * :cpp:func:`begin() <constexpr typename BaseType::iterator new_type::begin()>`
+ * :cpp:func:`begin() const <constexpr typename BaseType::iterator new_type::begin() const>`
+
+ .. versionadded:: 1.1.0
.. cpp:var:: auto constexpr Read = derivable<class read_tag>{}
@@ -750,7 +1136,7 @@ Standard derivation tags
.. cpp:var:: auto constexpr Relational = derivable<class relational_tag>{}
This tag enables the derivation of the following relational operators:
-
+
* :cpp:func:`operator\<(new_type const &, new_type const &) <template\<typename BaseType, typename TagType, auto DerivationClause> constexpr bool operator<(new_type<BaseType, TagType, DerivationClause> const &, new_type<BaseType, TagType, DerivationClause> const &)>`
* :cpp:func:`operator>(new_type const &, new_type const &) <template\<typename BaseType, typename TagType, auto DerivationClause> constexpr bool operator>(new_type<BaseType, TagType, DerivationClause> const &, new_type<BaseType, TagType, DerivationClause> const &)>`
* :cpp:func:`operator\<=(new_type const &, new_type const &) <template\<typename BaseType, typename TagType, auto DerivationClause> constexpr bool operator<=(new_type<BaseType, TagType, DerivationClause> const &, new_type<BaseType, TagType, DerivationClause> const &)>`
@@ -774,7 +1160,7 @@ Function template :cpp:func:`deriving`
.. cpp:function:: template<typename... DerivableTags> \
constexpr derivation_clause<DerivableTags...> deriving(derivable<DerivableTags>... features) noexcept
-
+
This function can be used to create a new :cpp:class:`derivation_clause` for use in the definitions of instances of :cpp:class:`new_type`.
.. versionadded:: 1.0.0
@@ -811,8 +1197,8 @@ Class template :cpp:class:`derivation_clause`
Check if this :cpp:class:`derivation clause <derivation_clause>` contains the given derivation
- :tparam DerivableTag: A tag uniquely identifying a derivation
-
+ :tparam DerivableTag: A tag uniquely identifying a derivation
+
.. cpp:function:: template<typename DerivableTag, typename... RemainingDerivableTags> \
constexpr bool operator()(derivable<DerivableTag>, derivable<RemainingDerivableTags>...) const noexcept
@@ -845,7 +1231,7 @@ Class template :cpp:class:`derivation_clause`
.. cpp:function:: template<typename... OtherDerivableTags> \
constexpr bool operator<(derivation_clause<OtherDerivableTags...> other) const noexcept
-
+
Check if this :cpp:class:`derivation clause <derivation_clause>` is a subset of the one represented by :cpp:any:`other`.
One :cpp:class:`derivation clause <derivation_clause>` is considered to be a subset of another iff. the list of derivations of this instance forms a proper subset of the list of derivations of the other.
diff --git a/doc8.ini b/doc8.ini
new file mode 100644
index 0000000..882336a
--- /dev/null
+++ b/doc8.ini
@@ -0,0 +1,2 @@
+[doc8]
+ignore=D001 \ No newline at end of file
diff --git a/include/newtype/derivable.hpp b/include/newtype/derivable.hpp
index 19c79d9..c798c59 100644
--- a/include/newtype/derivable.hpp
+++ b/include/newtype/derivable.hpp
@@ -12,73 +12,17 @@ namespace nt
using tag_type = DerivableTag;
};
- /**
- * @brief A set of standard derivation tags
- *
- * This convenience namespace contains all standard derivation tags.
- *
- * @since 1.0.0
- */
inline namespace derivables
{
- /**
- * @brief A tag to enable derivation of arithmetic operators
- *
- * @since 1.0.0
- */
auto constexpr Arithmetic = derivable<struct arithmetic_tag>{};
-
- /**
- * @brief A tag to enable derivation of "equality comparison with base type" operators
- *
- * @note Deriving this feature seriously weakens the using nt::new_type instance
- * @since 1.0.0
- */
auto constexpr EqBase = derivable<struct eq_base_tag>{};
-
- /**
- * @brief A tag to enable derivation of a specialization of std::hash
- *
- * @since 1.0.0
- */
auto constexpr Hash = derivable<struct hash_tag>{};
-
- /**
- * @brief A tag to enable derivation of the implicit "conversion to base type" operator
- *
- * @note If this tag is not present in the derivation clause of any given nt::new_type, the type instance only supports explicit
- * "conversion to base type"
- * @since 1.0.0
- */
auto constexpr ImplicitConversion = derivable<struct implicit_conversion_tag>{};
-
- /**
- * @brief A tag to enable access to the members of the base type object through a pointer
- *
- * @since 1.0.0
- */
auto constexpr Indirection = derivable<struct indirection_tag>{};
-
- /**
- * @brief A tag to enable derivation of the stream input operator
- *
- * @since 1.0.0
- */
+ auto constexpr Iterable = derivable<struct iterable_tag>{};
auto constexpr Read = derivable<struct read_tag>{};
-
- /**
- * @brief A tag to enable derivation of the relational operators
- *
- * @since 1.0.0
- */
auto constexpr Relational = derivable<struct relational_tag>{};
-
- /**
- * @brief A tag to enable derivation of the stream output operator
- *
- * @since 1.0.0
- */
auto constexpr Show = derivable<struct show_tag>{};
} // namespace derivables
diff --git a/include/newtype/derivation_clause.hpp b/include/newtype/derivation_clause.hpp
index edb2f85..6de70e1 100644
--- a/include/newtype/derivation_clause.hpp
+++ b/include/newtype/derivation_clause.hpp
@@ -9,11 +9,6 @@
namespace nt
{
- /**
- * A @p deriving clause type
- *
- * @tparam DerivableTags A list of tag types defining a set of derivable features
- */
template<typename... DerivableTags>
struct derivation_clause
{
@@ -21,88 +16,48 @@ namespace nt
{
}
- /**
- * Check whether the derivation clause contains a given derivable
- */
template<typename DerivableTag>
auto constexpr operator()(derivable<DerivableTag>) const noexcept -> bool
{
return (std::is_same_v<DerivableTags, DerivableTag> || ...);
}
- /**
- * Check whether the derivation clause contains all derivables in a given lists
- */
template<typename DerivableTag, typename... RemainingDerivableTags>
auto constexpr operator()(derivable<DerivableTag>, derivable<RemainingDerivableTags>...) const noexcept -> bool
{
return (*this)(derivable<DerivableTag>{}) && (*this)(derivable<RemainingDerivableTags>{}...);
}
- /**
- * Check whether this derivation clause is less than an other derivation clause
- *
- * A derivation clause is considered less than an other derivation clause iff. its set of derivables is a strict subset of
- * the set derivables of the other.
- */
template<typename... OtherDerivableTags>
auto constexpr operator<(derivation_clause<OtherDerivableTags...> other) const noexcept -> bool
{
return (sizeof...(DerivableTags) < sizeof...(OtherDerivableTags)) && other(derivable<DerivableTags>{}...);
}
- /**
- * Check whether this derivation clause is greater than an other derivation clause
- *
- * A derivation clause is considered greater than an other derivation clause iff. its set of derivables is a strict superset
- * of the set derivables of the other.
- */
template<typename... OtherDerivableTags>
auto constexpr operator>(derivation_clause<OtherDerivableTags...> other) const noexcept -> bool
{
return other < *this;
}
- /**
- * Check whether this derivation clause is equal to an other derivation clause
- *
- * Two derivation clauses are considered equal if both have the same set of derivables
- */
template<typename... OtherDerivableTags>
auto constexpr operator==(derivation_clause<OtherDerivableTags...> other) const noexcept -> bool
{
return sizeof...(DerivableTags) == sizeof...(OtherDerivableTags) && other(derivable<DerivableTags>{}...);
}
- /**
- * Check whether this derivation clause is not equal to an other derivation clause
- *
- * Two derivation clauses are considered not equal if neither has the same set of derivables as the other
- */
template<typename... OtherDerivableTags>
auto constexpr operator!=(derivation_clause<OtherDerivableTags...> other) const noexcept -> bool
{
return !(*this == other);
}
- /**
- * Check whether this derivation clause is less-than or equal to an other derivation clause
- *
- * @see nt::distinct::operator==
- * @see nt::distinct::operator<
- */
template<typename... OtherDerivableTags>
auto constexpr operator<=(derivation_clause<OtherDerivableTags...> other) const noexcept -> bool
{
return *this < other || *this == other;
}
- /**
- * Check whether this derivation clause is greater-than or equal to an other derivation clause
- *
- * @see nt::distinct::operator==
- * @see nt::distinct::operator<
- */
template<typename... OtherDerivableTags>
auto constexpr operator>=(derivation_clause<OtherDerivableTags...> other) const noexcept -> bool
{
diff --git a/include/newtype/deriving.hpp b/include/newtype/deriving.hpp
index e762c9b..ae10bab 100644
--- a/include/newtype/deriving.hpp
+++ b/include/newtype/deriving.hpp
@@ -10,9 +10,6 @@
namespace nt
{
- /**
- * Create a new derivation clause with the given derivables
- */
template<typename... DerivableTags>
auto constexpr deriving(derivable<DerivableTags>... features) noexcept -> derivation_clause<DerivableTags...>
{
diff --git a/include/newtype/impl/new_type_iterator_types.hpp b/include/newtype/impl/new_type_iterator_types.hpp
new file mode 100644
index 0000000..2ea8274
--- /dev/null
+++ b/include/newtype/impl/new_type_iterator_types.hpp
@@ -0,0 +1,66 @@
+#ifndef NEWTYPE_IMPL_NEW_TYPE_ITERATOR_TYPES_HPP
+#define NEWTYPE_IMPL_NEW_TYPE_ITERATOR_TYPES_HPP
+
+#include "newtype/version.hpp"
+
+#include <type_traits>
+
+namespace nt::impl
+{
+
+ template<typename T, bool = false, typename = std::void_t<>>
+ struct new_type_iterator
+ {
+ };
+
+ template<typename T>
+ struct new_type_iterator<T, true, std::void_t<typename T::iterator>>
+ {
+ using iterator = typename T::iterator;
+ };
+
+ template<typename T, bool = false, typename = std::void_t<>>
+ struct new_type_const_iterator
+ {
+ };
+
+ template<typename T>
+ struct new_type_const_iterator<T, true, std::void_t<typename T::const_iterator>>
+ {
+ using const_iterator = typename T::const_iterator;
+ };
+
+ template<typename T, bool = false, typename = std::void_t<>>
+ struct new_type_reverse_iterator
+ {
+ };
+
+ template<typename T>
+ struct new_type_reverse_iterator<T, true, std::void_t<typename T::reverse_iterator>>
+ {
+ using reverse_iterator = typename T::reverse_iterator;
+ };
+
+ template<typename T, bool = false, typename = std::void_t<>>
+ struct new_type_const_reverse_iterator
+ {
+ };
+
+ template<typename T>
+ struct new_type_const_reverse_iterator<T, true, std::void_t<typename T::const_reverse_iterator>>
+ {
+ using const_reverse_iterator = typename T::const_reverse_iterator;
+ };
+
+ template<typename T, bool Enabled>
+ struct new_type_iterator_types
+ : new_type_iterator<T, Enabled>
+ , new_type_const_iterator<T, Enabled>
+ , new_type_reverse_iterator<T, Enabled>
+ , new_type_const_reverse_iterator<T, Enabled>
+ {
+ };
+
+} // namespace nt::impl
+
+#endif \ No newline at end of file
diff --git a/include/newtype/impl/type_traits_extensions.hpp b/include/newtype/impl/type_traits_extensions.hpp
index 1f46fb4..dc41649 100644
--- a/include/newtype/impl/type_traits_extensions.hpp
+++ b/include/newtype/impl/type_traits_extensions.hpp
@@ -14,125 +14,57 @@ namespace nt::impl
inline namespace equality_comparable
{
- /**
- * @brief A trait to test if a given type is comparable using operator==
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-equals-comparable T
- */
template<typename T, typename = void>
struct is_equality_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is comparable using operator==
- *
- * @tparam T The type to test
- * @note This specialization forms the case for equals-comparable T
- */
template<typename T>
struct is_equality_comparable<T, std::void_t<decltype(std::declval<T const &>() == std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is comparable using operator==
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_equality_comparable_v = is_equality_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator==
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept equals-comparable or non-equals-comparable T
- */
template<typename T, typename = void>
struct is_nothrow_equality_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator==
- *
- * @tparam T The type to test
- * @note This specialization forms the case for equals-comparable T detemining if T is noexcept comparable using operator==
- */
template<typename T>
struct is_nothrow_equality_comparable<T, std::void_t<decltype(std::declval<T const &>() == std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() == std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept comparable using operator==
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_equality_comparable_v = is_nothrow_equality_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is comparable using operator!=
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-not-equals-comparable T
- */
template<typename T, typename = void>
struct is_inequality_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is comparable using operator!=
- *
- * @tparam T The type to test
- * @note This specialization forms the case for not-equals-comparable T
- */
template<typename T>
struct is_inequality_comparable<T, std::void_t<decltype(std::declval<T const &>() != std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is comparable using operator!=
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_inequality_comparable_v = is_inequality_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator!=
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept not-equals-comparable or non-not-equals-comparable T
- */
template<typename T, typename = void>
struct is_nothrow_inequality_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator==
- *
- * @tparam T The type to test
- * @note This specialization forms the case for equals-comparable T detemining if T is noexcept comparable using operator!=
- */
template<typename T>
struct is_nothrow_inequality_comparable<T, std::void_t<decltype(std::declval<T const &>() != std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() != std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept comparable using operator!=
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_inequality_comparable_v = is_nothrow_inequality_comparable<T>::value;
@@ -141,250 +73,112 @@ namespace nt::impl
inline namespace relationally_comparable
{
- /**
- * @brief A trait to test if a given type is comparable using operator<
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-less-than-comparable T
- */
template<typename T, typename = void>
struct is_less_than_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is comparable using operator<
- *
- * @tparam T The type to test
- * @note This specialization forms the case for less-than-comparable T
- */
template<typename T>
struct is_less_than_comparable<T, std::void_t<decltype(std::declval<T const &>() < std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is comparable using operator<
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_less_than_comparable_v = is_less_than_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator<
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept less-than-comparable or non-less-than-comparable T
- */
template<typename T, typename = void>
struct is_nothrow_less_than_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator<
- *
- * @tparam T The type to test
- * @note This specialization forms the case for less-than-comparable T detemining if T is noexcept comparable using operator<
- */
template<typename T>
struct is_nothrow_less_than_comparable<T, std::void_t<decltype(std::declval<T const &>() < std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() < std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept comparable using operator<
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_less_than_comparable_v = is_nothrow_less_than_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is comparable using operator>
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-greater-than-comparable T
- */
template<typename T, typename = void>
struct is_greater_than_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is comparable using operator>
- *
- * @tparam T The type to test
- * @note This specialization forms the case for greater-than-comparable T
- */
template<typename T>
struct is_greater_than_comparable<T, std::void_t<decltype(std::declval<T const &>() > std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is comparable using operator>
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_greater_than_comparable_v = is_greater_than_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator>
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept greater-than-comparable or non-greater-than-comparable T
- */
template<typename T, typename = void>
struct is_nothrow_greater_than_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator>
- *
- * @tparam T The type to test
- * @note This specialization forms the case for greater-than-comparable T detemining if T is noexcept comparable using operator>
- */
template<typename T>
struct is_nothrow_greater_than_comparable<T, std::void_t<decltype(std::declval<T const &>() > std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() > std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept comparable using operator>
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_greater_than_comparable_v = is_nothrow_greater_than_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is comparable using operator<=
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-less-than-or-equal-to-comparable T
- */
template<typename T, typename = void>
struct is_less_than_equal_to_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is comparable using operator<=
- *
- * @tparam T The type to test
- * @note This specialization forms the case for less-than-or-equal-to-comparable T
- */
template<typename T>
struct is_less_than_equal_to_comparable<T, std::void_t<decltype(std::declval<T const &>() <= std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is comparable using operator<=
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_less_than_equal_to_comparable_v = is_less_than_equal_to_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator<=
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept less-than-or-equal-to-comparable or non-less-than-or-equal-to-comparable T
- */
template<typename T, typename = void>
struct is_nothrow_less_than_equal_to_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator<=
- *
- * @tparam T The type to test
- * @note This specialization forms the case for less-than-or-equal-to-comparable T detemining if T is noexcept comparable using operator<=
- */
template<typename T>
struct is_nothrow_less_than_equal_to_comparable<T, std::void_t<decltype(std::declval<T const &>() <= std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() <= std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept comparable using operator<=
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_less_than_equal_to_comparable_v = is_nothrow_less_than_equal_to_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is comparable using operator>=
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-greater-than-or-equal-to-comparable T
- */
template<typename T, typename = void>
struct is_greater_than_equal_to_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is comparable using operator>=
- *
- * @tparam T The type to test
- * @note This specialization forms the case for greater-than-or-equal-to-comparable T
- */
template<typename T>
struct is_greater_than_equal_to_comparable<T, std::void_t<decltype(std::declval<T const &>() >= std::declval<T const &>())>>
: std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is comparable using operator>=
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_greater_than_equal_to_comparable_v = is_greater_than_equal_to_comparable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator>=
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept greater-than-or-equal-to-comparable or
- * non-greater-than-or-equal-to-comparable T
- */
template<typename T, typename = void>
struct is_nothrow_greater_than_equal_to_comparable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept comparable using operator>=
- *
- * @tparam T The type to test
- * @note This specialization forms the case for greater-than-or-equal-to-comparable T detemining if T is noexcept comparable using
- * operator>=
- */
template<typename T>
struct is_nothrow_greater_than_equal_to_comparable<T, std::void_t<decltype(std::declval<T const &>() >= std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() >= std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept comparable using operator>=
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_greater_than_equal_to_comparable_v = is_nothrow_greater_than_equal_to_comparable<T>::value;
} // namespace relationally_comparable
@@ -392,126 +186,58 @@ namespace nt::impl
inline namespace iostreamable
{
- /**
- * @brief A trait to test if a given type is output streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-output-streamable T
- */
template<typename StreamType, typename T, typename = void>
struct is_output_streamable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is output streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for output-streamable T
- */
template<typename StreamType, typename T>
struct is_output_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() << std::declval<T const &>())>>
: std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is output streamable
- *
- * @tparam T The type to test
- */
template<typename StreamType, typename T>
auto constexpr is_output_streamable_v = is_output_streamable<StreamType, T>::value;
- /**
- * @brief A trait to test if a given type is noexcept output streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept output-streamable or non-output-streamable T
- */
template<typename StreamType, typename T, typename = void>
struct is_nothrow_output_streamable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept output streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for output-streamable T detemining if T is noexcept output-streamable
- */
template<typename StreamType, typename T>
struct is_nothrow_output_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() << std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<StreamType &>() << std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept output streamable
- *
- * @tparam T The type to test
- */
template<typename StreamType, typename T>
auto constexpr is_nothrow_output_streamable_v = is_nothrow_output_streamable<StreamType, T>::value;
- /**
- * @brief A trait to test if a given type is input streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-input-streamable T
- */
template<typename StreamType, typename T, typename = void>
struct is_input_streamable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is input streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for input-streamable T
- */
template<typename StreamType, typename T>
struct is_input_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() >> std::declval<T &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is input streamable
- *
- * @tparam T The type to test
- */
template<typename StreamType, typename T>
auto constexpr is_input_streamable_v = is_input_streamable<StreamType, T>::value;
- /**
- * @brief A trait to test if a given type is noexcept input streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept input-streamable or non-input-streamable T
- */
template<typename StreamType, typename T, typename = void>
struct is_nothrow_input_streamable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept input streamable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for input-streamable T detemining if T is noexcept input-streamable
- */
template<typename StreamType, typename T>
struct is_nothrow_input_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() >> std::declval<T &>())>>
: std::bool_constant<noexcept(std::declval<StreamType &>() >> std::declval<T &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept input streamable
- *
- * @tparam T The type to test
- */
template<typename StreamType, typename T>
auto constexpr is_nothrow_input_streamable_v = is_nothrow_input_streamable<StreamType, T>::value;
@@ -520,247 +246,111 @@ namespace nt::impl
inline namespace arithmetic
{
- /**
- * @brief A trait to test if a given type is addable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-addable T
- */
template<typename T, typename = void>
struct is_addable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is addable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for addable T
- */
template<typename T>
struct is_addable<T, std::void_t<decltype(std::declval<T const &>() + std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is addable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_addable_v = is_addable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept addable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept addable or non-addable T
- */
template<typename T, typename = void>
struct is_nothrow_addable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept addable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for addable T detemining if T is noexcept addable
- */
template<typename T>
struct is_nothrow_addable<T, std::void_t<decltype(std::declval<T const &>() + std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() + std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept addable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_addable_v = is_nothrow_addable<T>::value;
- /**
- * @brief A trait to test if a given type is subtractable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-subtractable T
- */
template<typename T, typename = void>
struct is_subtractable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is subtractable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for subtractable T
- */
template<typename T>
struct is_subtractable<T, std::void_t<decltype(std::declval<T const &>() - std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is subtractable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_subtractable_v = is_subtractable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept subtractable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept subtractable or non-subtractable T
- */
template<typename T, typename = void>
struct is_nothrow_subtractable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept subtractable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for subtractable T detemining if T is noexcept subtractable
- */
template<typename T>
struct is_nothrow_subtractable<T, std::void_t<decltype(std::declval<T const &>() - std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() - std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept subtractable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_subtractable_v = is_nothrow_subtractable<T>::value;
- /**
- * @brief A trait to test if a given type is multipliable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-multipliable T
- */
template<typename T, typename = void>
struct is_multipliable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is multipliable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for multipliable T
- */
template<typename T>
struct is_multipliable<T, std::void_t<decltype(std::declval<T const &>() * std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is multipliable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_multipliable_v = is_multipliable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept multipliable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept multipliable or non-multipliable T
- */
template<typename T, typename = void>
struct is_nothrow_multipliable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept multipliable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for multipliable T detemining if T is noexcept multipliable
- */
template<typename T>
struct is_nothrow_multipliable<T, std::void_t<decltype(std::declval<T const &>() * std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() * std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept multipliable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_multipliable_v = is_nothrow_multipliable<T>::value;
- /**
- * @brief A trait to test if a given type is dividable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-dividable T
- */
template<typename T, typename = void>
struct is_dividable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is dividable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for dividable T
- */
template<typename T>
struct is_dividable<T, std::void_t<decltype(std::declval<T const &>() / std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is dividable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_dividable_v = is_dividable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept dividable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept dividable or non-dividable T
- */
template<typename T, typename = void>
struct is_nothrow_dividable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept dividable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for dividable T detemining if T is noexcept dividable
- */
template<typename T>
struct is_nothrow_dividable<T, std::void_t<decltype(std::declval<T const &>() / std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T const &>() / std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept dividable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_dividable_v = is_nothrow_dividable<T>::value;
@@ -769,247 +359,111 @@ namespace nt::impl
inline namespace compound_arithmetic
{
- /**
- * @brief A trait to test if a given type is add-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-add-assignable T
- */
template<typename T, typename = void>
struct is_add_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is add-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for add-assignable T
- */
template<typename T>
struct is_add_assignable<T, std::void_t<decltype(std::declval<T &>() += std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is add-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_add_assignable_v = is_add_assignable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept add-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept add-assignable or non-add-assignable T
- */
template<typename T, typename = void>
struct is_nothrow_add_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept add-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for add-assignable T detemining if T is noexcept add-assignable
- */
template<typename T>
struct is_nothrow_add_assignable<T, std::void_t<decltype(std::declval<T &>() += std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T &>() += std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept add-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_add_assignable_v = is_nothrow_add_assignable<T>::value;
- /**
- * @brief A trait to test if a given type is subtract-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-subtract-assignable T
- */
template<typename T, typename = void>
struct is_subtract_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is subtract-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for subtract-assignable T
- */
template<typename T>
struct is_subtract_assignable<T, std::void_t<decltype(std::declval<T &>() -= std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is subtract-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_subtract_assignable_v = is_subtract_assignable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept subtract-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept subtract-assignable or non-subtract-assignable T
- */
template<typename T, typename = void>
struct is_nothrow_subtract_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept subtract-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for subtract-assignable T detemining if T is noexcept subtract-assignable
- */
template<typename T>
struct is_nothrow_subtract_assignable<T, std::void_t<decltype(std::declval<T &>() -= std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T &>() -= std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept subtract-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_subtract_assignable_v = is_nothrow_subtract_assignable<T>::value;
- /**
- * @brief A trait to test if a given type is multiply-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-multiply-assignable T
- */
template<typename T, typename = void>
struct is_multiply_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is multiply-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for multiply-assignable T
- */
template<typename T>
struct is_multiply_assignable<T, std::void_t<decltype(std::declval<T &>() *= std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is multiply-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_multiply_assignable_v = is_multiply_assignable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept multiply-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept multiply-assignable or non-multiply-assignable T
- */
template<typename T, typename = void>
struct is_nothrow_multiply_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept multiply-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for multiply-assignable T detemining if T is noexcept multiply-assignable
- */
template<typename T>
struct is_nothrow_multiply_assignable<T, std::void_t<decltype(std::declval<T &>() *= std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T &>() *= std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept multiply-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_multiply_assignable_v = is_nothrow_multiply_assignable<T>::value;
- /**
- * @brief A trait to test if a given type is divide-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-divide-assignable T
- */
template<typename T, typename = void>
struct is_divide_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is divide-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for divide-assignable T
- */
template<typename T>
struct is_divide_assignable<T, std::void_t<decltype(std::declval<T &>() /= std::declval<T const &>())>> : std::true_type
{
};
- /**
- * @brief A variable template to test if a given type is divide-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_divide_assignable_v = is_divide_assignable<T>::value;
- /**
- * @brief A trait to test if a given type is noexcept divide-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-noexcept divide-assignable or non-divide-assignable T
- */
template<typename T, typename = void>
struct is_nothrow_divide_assignable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is noexcept divide-assignable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for divide-assignable T detemining if T is noexcept divide-assignable
- */
template<typename T>
struct is_nothrow_divide_assignable<T, std::void_t<decltype(std::declval<T &>() /= std::declval<T const &>())>>
: std::bool_constant<noexcept(std::declval<T &>() /= std::declval<T const &>())>
{
};
- /**
- * @brief A variable template to test if a given type is noexcept divide-assignable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_nothrow_divide_assignable_v = is_nothrow_divide_assignable<T>::value;
@@ -1018,39 +472,382 @@ namespace nt::impl
inline namespace std_support
{
- /**
- * @brief A trait to test if a given type is hashable
- *
- * @tparam T The type to test
- * @note This specialization forms the base case for non-hashable T
- */
template<typename T, typename = void>
struct is_hashable : std::false_type
{
};
- /**
- * @brief A trait to test if a given type is hashable
- *
- * @tparam T The type to test
- * @note This specialization forms the case for hashable T
- */
template<typename T>
struct is_hashable<T, std::void_t<decltype(std::declval<std::hash<T> const &>()(std::declval<T const &>()))>>
: std::is_same<std::size_t, decltype(std::declval<std::hash<T> const &>()(std::declval<T const &>()))>
{
};
- /**
- * @brief A variable template to test if a given type is hashable
- *
- * @tparam T The type to test
- */
template<typename T>
auto constexpr is_hashable_v = is_hashable<T>::value;
} // namespace std_support
+ inline namespace iterable_begin
+ {
+ template<typename T, typename = void>
+ struct has_free_begin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_begin<T, std::void_t<decltype(begin(std::declval<T &>()))>>
+ : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(begin(std::declval<T &>()))>>
+ {
+ };
+
+ template<typename T>
+ struct has_free_begin<T const, std::void_t<decltype(begin(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(begin(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_begin_v = has_free_begin<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_begin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_begin<T, std::void_t<decltype(std::declval<T &>().begin())>>
+ : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(std::declval<T &>().begin())>>
+ {
+ };
+
+ template<typename T>
+ struct has_member_begin<T const, std::void_t<decltype(std::declval<T const &>().begin())>>
+ : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().begin())>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_begin_v = has_member_begin<T>::value;
+
+ template<typename T>
+ struct has_begin : std::disjunction<has_free_begin<T>, has_member_begin<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_begin_v = has_begin<T>::value;
+ } // namespace iterable_begin
+
+ inline namespace iterable_cbegin
+ {
+ template<typename T, typename = void>
+ struct has_free_cbegin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_cbegin<T, std::void_t<decltype(cbegin(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(cbegin(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_cbegin_v = has_free_cbegin<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_cbegin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_cbegin<T, std::void_t<decltype(std::declval<T const &>().cbegin())>>
+ : std::is_same<typename T::const_iterator, decltype(std::declval<T const &>().cbegin())>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_cbegin_v = has_member_cbegin<T>::value;
+
+ template<typename T>
+ struct has_cbegin : std::disjunction<has_free_cbegin<T>, has_member_cbegin<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_cbegin_v = has_cbegin<T>::value;
+ } // namespace iterable_cbegin
+
+ inline namespace iterable_rbegin
+ {
+ template<typename T, typename = void>
+ struct has_free_rbegin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_rbegin<T, std::void_t<decltype(rbegin(std::declval<T &>()))>>
+ : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(rbegin(std::declval<T &>()))>>
+ {
+ };
+
+ template<typename T>
+ struct has_free_rbegin<T const, std::void_t<decltype(rbegin(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(rbegin(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_rbegin_v = has_free_rbegin<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_rbegin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_rbegin<T, std::void_t<decltype(std::declval<T &>().rbegin())>>
+ : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(std::declval<T &>().rbegin())>>
+ {
+ };
+
+ template<typename T>
+ struct has_member_rbegin<T const, std::void_t<decltype(std::declval<T const &>().rbegin())>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().rbegin())>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_rbegin_v = has_member_rbegin<T>::value;
+
+ template<typename T>
+ struct has_rbegin : std::disjunction<has_free_rbegin<T>, has_member_rbegin<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_rbegin_v = has_rbegin<T>::value;
+ } // namespace iterable_rbegin
+
+ inline namespace iterable_crbegin
+ {
+ template<typename T, typename = void>
+ struct has_free_crbegin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_crbegin<T, std::void_t<decltype(crbegin(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(crbegin(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_crbegin_v = has_free_crbegin<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_crbegin : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_crbegin<T, std::void_t<decltype(std::declval<T const &>().crbegin())>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().crbegin())>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_crbegin_v = has_member_crbegin<T>::value;
+
+ template<typename T>
+ struct has_crbegin : std::disjunction<has_free_crbegin<T>, has_member_crbegin<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_crbegin_v = has_crbegin<T>::value;
+ } // namespace iterable_crbegin
+
+ inline namespace iterable_end
+ {
+ template<typename T, typename = void>
+ struct has_free_end : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_end<T, std::void_t<decltype(end(std::declval<T &>()))>>
+ : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(end(std::declval<T &>()))>>
+ {
+ };
+
+ template<typename T>
+ struct has_free_end<T const, std::void_t<decltype(end(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(end(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_end_v = has_free_end<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_end : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_end<T, std::void_t<decltype(std::declval<T &>().end())>>
+ : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(std::declval<T &>().end())>>
+ {
+ };
+
+ template<typename T>
+ struct has_member_end<T const, std::void_t<decltype(std::declval<T const &>().end())>>
+ : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().end())>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_end_v = has_member_end<T>::value;
+
+ template<typename T>
+ struct has_end : std::disjunction<has_free_end<T>, has_member_end<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_end_v = has_end<T>::value;
+ } // namespace iterable_end
+
+ inline namespace iterable_cend
+ {
+ template<typename T, typename = void>
+ struct has_free_cend : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_cend<T, std::void_t<decltype(cend(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(cend(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_cend_v = has_free_cend<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_cend : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_cend<T, std::void_t<decltype(std::declval<T const &>().cend())>>
+ : std::is_same<typename T::const_iterator, decltype(std::declval<T const &>().cend())>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_cend_v = has_member_cend<T>::value;
+
+ template<typename T>
+ struct has_cend : std::disjunction<has_free_cend<T>, has_member_cend<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_cend_v = has_cend<T>::value;
+ } // namespace iterable_cend
+
+ inline namespace iterable_rend
+ {
+ template<typename T, typename = void>
+ struct has_free_rend : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_rend<T, std::void_t<decltype(rend(std::declval<T &>()))>>
+ : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(rend(std::declval<T &>()))>>
+ {
+ };
+
+ template<typename T>
+ struct has_free_rend<T const, std::void_t<decltype(rend(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(rend(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_rend_v = has_free_rend<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_rend : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_rend<T, std::void_t<decltype(std::declval<T &>().rend())>>
+ : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(std::declval<T &>().rend())>>
+ {
+ };
+
+ template<typename T>
+ struct has_member_rend<T const, std::void_t<decltype(std::declval<T const &>().rend())>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().rend())>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_rend_v = has_member_rend<T>::value;
+
+ template<typename T>
+ struct has_rend : std::disjunction<has_free_rend<T>, has_member_rend<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_rend_v = has_rend<T>::value;
+ } // namespace iterable_rend
+
+ inline namespace iterable_crend
+ {
+ template<typename T, typename = void>
+ struct has_free_crend : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_free_crend<T, std::void_t<decltype(crend(std::declval<T const &>()))>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(crend(std::declval<T const &>()))>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_free_crend_v = has_free_crend<T>::value;
+
+ template<typename T, typename = void>
+ struct has_member_crend : std::false_type
+ {
+ };
+
+ template<typename T>
+ struct has_member_crend<T, std::void_t<decltype(std::declval<T const &>().crend())>>
+ : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().crend())>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_member_crend_v = has_member_crend<T>::value;
+
+ template<typename T>
+ struct has_crend : std::disjunction<has_free_crend<T>, has_member_crend<T>>
+ {
+ };
+
+ template<typename T>
+ auto constexpr has_crend_v = has_crend<T>::value;
+ } // namespace iterable_crend
+
} // namespace nt::impl
#endif \ No newline at end of file
diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp
index ed1de44..66ff332 100644
--- a/include/newtype/new_type.hpp
+++ b/include/newtype/new_type.hpp
@@ -3,6 +3,7 @@
#include "newtype/derivable.hpp"
#include "newtype/deriving.hpp"
+#include "newtype/impl/new_type_iterator_types.hpp"
#include "newtype/impl/new_type_storage.hpp"
#include "newtype/impl/type_traits_extensions.hpp"
#include "newtype/version.hpp"
@@ -15,18 +16,10 @@
namespace nt
{
- /**
- * @brief Create a new type based on an existing one
- *
- * The class template nt::new_type is designed to allow the creation of new types based on existing types. Similarly to the Haskell newtype,
- * this class template creates a new type that is layout equivalent to the underlying type.
- *
- * @tparam BaseType An existing type that shall aliased
- * @tparam TagType A unique type to identify this nt::new_type
- * @tparam DervivationClause An nt::derivation_clause describing which features shall be automatically derived for the new type alias
- */
template<typename BaseType, typename TagType, auto DerivationClause = deriving()>
- class new_type : impl::new_type_move_assignment<BaseType, TagType>
+ class new_type
+ : impl::new_type_move_assignment<BaseType, TagType>
+ , public impl::new_type_iterator_types<BaseType, DerivationClause(nt::Iterable)>
{
static_assert(!std::is_reference_v<BaseType>, "The base type must not be a reference type");
static_assert(!std::is_void_v<std::remove_cv_t<BaseType>>, "The base type must not be possibly cv-qualified void");
@@ -65,161 +58,198 @@ namespace nt
-> std::enable_if_t<DerivationClauseV(nt::Arithmetic) && impl::is_divide_assignable_v<BaseTypeT>,
new_type<BaseTypeT, TagTypeT, DerivationClauseV> &>;
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend begin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_begin_v<BaseTypeT>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend begin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_begin_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend cbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_cbegin_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rbegin_v<BaseTypeT>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::reverse_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rbegin_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend crbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_crbegin_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend end(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_end_v<BaseTypeT>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend end(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_end_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend cend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_cend_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend rend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rend_v<BaseTypeT>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::reverse_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend rend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rend_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>;
+
+ template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV>
+ auto constexpr friend crend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj)
+ -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_crend_v<BaseTypeT const>,
+ typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>;
+
using super = impl::new_type_move_assignment<BaseType, TagType>;
public:
- /// @section Type aliases
-
- /**
- * @brief The base type of this nt::new_type
- *
- * This type alias provides convenient access to the contained objects type
- */
using base_type = BaseType;
-
- /**
- * @brief The tag type of this nt::new_type
- *
- * This type alias provides convenient access to the tag type of this nt::new_type instance
- */
using tag_type = TagType;
-
- /**
- * @brief The type of the derivation clause of this nt::newtype
- *
- * This type alias provides convenient access to the type of the derivation clause of this nt::new_type instance
- */
using derivation_clause_type = decltype(DerivationClause);
- /// @section Derivation clause access
-
- /**
- * @brief The derivation clause fo this nt::new_type
- *
- * This static data-member provides conevient access to the derivation clause of this nt::new_type instance
- */
auto constexpr static derivation_clause = DerivationClause;
- /// @section Constructors
-
using super::super;
- /**
- * @brief Construct an instance of this nt::new_type by default initializing the contained object
- *
- * @note This constructor is available iff. the base type is default-constructible. Otherwise is is defined as deleted.
- * @throw This constructor throws any exception thrown the base type constructor. It is noexcept iff. the base type constructor is noexcept
- */
constexpr new_type() noexcept(std::is_nothrow_default_constructible_v<BaseType>) = default;
-
- /**
- * @brief Copy-construct an instance of this nt::new_type from an existing one
- *
- * @note This constructor is available iff. the base type is copy-constructible. Otherwise is is defined as deleted.
- * @throw This constructor throws any exception thrown the base type copy-constructor. It is noexcept iff. the base type copy-constructor
- * is noexcept
- */
constexpr new_type(new_type const &) noexcept(std::is_nothrow_copy_constructible_v<BaseType>) = default;
-
- /**
- * @brief Move-construct an instance of this nt::new_type from an existing one
- *
- * @note This constructor is available iff. the base type is move-constructible. Otherwise is is defined as deleted.
- * @throw This constructor throws any exception thrown the base type move-constructor. It is noexcept iff. the base types move-constructor
- * is noexcept
- */
constexpr new_type(new_type &&) noexcept(std::is_nothrow_move_constructible_v<BaseType>) = default;
- /// @section Assignment operators
-
- /**
- * @brief Copy-assign the value of an existing instance of this nt::new_type to this instance
- *
- * @note This assignment operator is available iff. the base type is copy-assignable. Otherwise it is defined as deleted.
- * @throw This assignment operator throws any exception thrown by the base type copy-assignment operator. It is noexcept iff. the base type
- * copy-assignment operator is noexcept.
- * @return A reference to this instance
- */
auto constexpr operator=(new_type const &) noexcept(std::is_nothrow_copy_assignable_v<BaseType>) -> new_type & = default;
-
- /**
- * @brief Move-assign the value of an existing instance of this nt::new_type to this instance
- *
- * @note This assignment operator is available iff. the base type is move-assignable. Otherwise it is defined as deleted.
- * @throw This assignment operator throws any exception thrown by the base type move-assignment operator. It is noexcept iff. the base type
- * move-assignment operator is noexcept.
- * @return A reference to this instance
- */
auto constexpr operator=(new_type &&) noexcept(std::is_nothrow_move_assignable_v<BaseType>) -> new_type & = default;
- /// @section Accessors
-
- /**
- * @brief Obtain a copy of the contained base type object
- *
- * @return BaseType
- */
auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v<BaseType>) -> BaseType
{
return this->m_value;
}
- /**
- * @brief Convert this instance into the equivalent base type value
- *
- * @note This is only available if the derivation clause of this nt::new_type contains nt::ImplicitConversion
- */
template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::ImplicitConversion)> * = nullptr>
constexpr operator base_type() const noexcept(std::is_nothrow_copy_constructible_v<base_type>)
{
return decay();
}
- /**
- * @brief Convert this instance into the equivalent base type value
- *
- * @note This overload is only avalaible if the derivation clause of this nt::new_type does not contain nt::ImplicitConversion
- */
template<typename NewType = new_type, std::enable_if_t<!NewType::derivation_clause(nt::ImplicitConversion)> * = nullptr>
explicit constexpr operator base_type() const noexcept(std::is_nothrow_copy_constructible_v<base_type>)
{
return decay();
}
- /// @section Indirection operators
-
- /**
- * @brief Perform an access to a member of the base type
- *
- * @return A pointer to the contained base type object
- */
template<typename NewType = new_type>
auto constexpr operator-> () noexcept -> std::enable_if_t<NewType::derivation_clause(nt::Indirection), BaseType *>
{
return std::addressof(this->m_value);
}
- /**
- * @brief Perform an access to a member of the base type
- *
- * @return A pointer to the contained base type object
- */
template<typename NewType = new_type>
auto constexpr operator-> () const noexcept -> std::enable_if_t<NewType::derivation_clause(nt::Indirection), BaseType const *>
{
return std::addressof(this->m_value);
}
- };
- /// @section Equality comparison operators
+ template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr>
+ auto constexpr begin()
+ -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_begin_v<BaseType>, typename NewType::iterator>
+ {
+ return this->m_value.begin();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr begin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_begin_v<BaseType const>,
+ typename NewType::const_iterator>
+ {
+ return this->m_value.begin();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr cbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_cbegin_v<BaseType const>,
+ typename NewType::const_iterator>
+ {
+ return this->m_value.cbegin();
+ }
+
+ template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr>
+ auto constexpr rbegin()
+ -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rbegin_v<BaseType>, typename NewType::reverse_iterator>
+ {
+ return this->m_value.rbegin();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr rbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rbegin_v<BaseType const>,
+ typename NewType::const_reverse_iterator>
+ {
+ return this->m_value.rbegin();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr crbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_crbegin_v<BaseType const>,
+ typename NewType::const_reverse_iterator>
+ {
+ return this->m_value.crbegin();
+ }
+
+ template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr>
+ auto constexpr end()
+ -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_end_v<BaseType>, typename NewType::iterator>
+ {
+ return this->m_value.end();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr end() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_end_v<BaseType const>,
+ typename NewType::const_iterator>
+ {
+ return this->m_value.end();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr cend() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_cend_v<BaseType const>,
+ typename NewType::const_iterator>
+ {
+ return this->m_value.cend();
+ }
+
+ template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr>
+ auto constexpr rend()
+ -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rend_v<BaseType>, typename NewType::reverse_iterator>
+ {
+ return this->m_value.rend();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr rend() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rend_v<BaseType const>,
+ typename NewType::const_reverse_iterator>
+ {
+ return this->m_value.rend();
+ }
+
+ template<typename NewType = new_type>
+ auto constexpr crend() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_crend_v<BaseType const>,
+ typename NewType::const_reverse_iterator>
+ {
+ return this->m_value.crend();
+ }
+ };
- /**
- * @brief Compare two objects for equality
- *
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator==(new_type<BaseType, TagType, DerivationClause> const & lhs,
@@ -229,13 +259,6 @@ namespace nt
return lhs.decay() == rhs.decay();
}
- /**
- * @brief Compare an instance of a given nt::new_type with an object of its base type
- *
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr operator==(new_type<BaseType, TagType, DerivationClause> const & lhs,
BaseType const & rhs) noexcept(impl::is_nothrow_equality_comparable_v<BaseType>)
@@ -244,13 +267,6 @@ namespace nt
return lhs.decay() == rhs;
}
- /**
- * @brief Compare an instance of the base type with an instance of a given nt::new_type
- *
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator==(BaseType const & lhs,
@@ -260,13 +276,6 @@ namespace nt
return lhs == rhs.decay();
}
- /**
- * @brief Compare two objects for non-equality
- *
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator!=(new_type<BaseType, TagType, DerivationClause> const & lhs,
@@ -276,13 +285,6 @@ namespace nt
return lhs.decay() != rhs.decay();
}
- /**
- * @brief Compare an instance of a given nt::new_type with an object of its base type
- *
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr operator!=(new_type<BaseType, TagType, DerivationClause> const & lhs,
BaseType const & rhs) noexcept(impl::is_nothrow_inequality_comparable_v<BaseType>)
@@ -291,13 +293,6 @@ namespace nt
return lhs.decay() != rhs;
}
- /**
- * @brief Compare an instance of the base type with an instance of a given nt::new_type
- *
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator!=(BaseType const & lhs,
@@ -307,17 +302,6 @@ namespace nt
return lhs != rhs.decay();
}
- /// @section Relational operators
-
- /**
- * @brief Check if one nt::new_type object is less-than an other
- *
- * @note This operator is only available if the the derivation clause of this nt::new_type does contains nt::Relational and the base type is
- * less-than comparable.
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator<(new_type<BaseType, TagType, DerivationClause> const & lhs,
@@ -327,15 +311,6 @@ namespace nt
return lhs.decay() < rhs.decay();
}
- /**
- * Check if one nt::new_type object is greater-than an other
- *
- * @note This operator is only available if the the derivation clause of this nt::new_type does contains nt::Relational and the base type is
- * greater-than comparable.
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator>(new_type<BaseType, TagType, DerivationClause> const & lhs,
@@ -345,15 +320,6 @@ namespace nt
return lhs.decay() > rhs.decay();
}
- /**
- * Check if one nt::new_type object is less-than or equal-to an other
- *
- * @note This operator is only available if the the derivation clause of this nt::new_type does contains nt::Relational and the base type is
- * less-than-or-equal-to comparable.
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator<=(new_type<BaseType, TagType, DerivationClause> const & lhs,
@@ -363,15 +329,6 @@ namespace nt
return lhs.decay() <= rhs.decay();
}
- /**
- * Check if one nt::new_type object is greater-than or equal-to an other
- *
- * @note This operator is only available if the the derivation clause of this nt::new_type does contains nt::Relational and the base type is
- * greater-than-or-equal comparable
- * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
- * comparison operator is noexcept.
- * @return true iff. the base type comparison operator returns true, false otherwise.
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator>=(new_type<BaseType, TagType, DerivationClause> const & lhs,
@@ -381,16 +338,6 @@ namespace nt
return lhs.decay() >= rhs.decay();
}
- /// @section Stream input/output operators
-
- /**
- * @brief Write the contained base type object to a standard output stream
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type object contains nt::Show.
- * @param output The output stream to write to
- * @param source An instance of an nt::new_type that shall be written to the stream
- * @return The a reference to the output stream
- */
template<typename BaseType, typename TagType, auto DerivationClause, typename CharType, typename StreamTraits>
auto operator<<(std::basic_ostream<CharType, StreamTraits> & output, new_type<BaseType, TagType, DerivationClause> const & source) noexcept(
impl::is_nothrow_output_streamable_v<std::basic_ostream<CharType, StreamTraits>, BaseType>)
@@ -400,14 +347,6 @@ namespace nt
return output << source.decay();
}
- /**
- * @brief Read an object of the base type from a standard input stream
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type object contains nt::Read.
- * @param output The input stream to read from
- * @param source An instance of an nt::new_type that shall be read from the stream
- * @return The a reference to the input stream
- */
template<typename BaseType, typename TagType, auto DerivationClause, typename CharType, typename StreamTraits>
auto operator>>(std::basic_istream<CharType, StreamTraits> & input, new_type<BaseType, TagType, DerivationClause> & target) noexcept(
impl::is_nothrow_input_streamable_v<std::basic_istream<CharType, StreamTraits>, BaseType>)
@@ -417,17 +356,6 @@ namespace nt
return input >> target.m_value;
}
- /// @section Arithmetic operators
-
- /**
- * @brief Add two instances of the same nt::new_type
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is addable.
- * @param lhs The left-hand side of the addition
- * @param rhs The right-hand side of the addition
- * @return a new instance of the same nt::new_type
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator+(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(
@@ -437,15 +365,6 @@ namespace nt
return {lhs.decay() + rhs.decay()};
}
- /**
- * @brief Add two instances of the same nt::new_type, modifying the left-hand side
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is addable.
- * @param lhs The left-hand side of the addition
- * @param rhs The right-hand side of the addition
- * @return a reference to the the modified value
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr operator+=(new_type<BaseType, TagType, DerivationClause> & lhs,
new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_add_assignable_v<BaseType>)
@@ -456,15 +375,6 @@ namespace nt
return lhs;
}
- /**
- * @brief Subtract two instances of the same nt::new_type
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is subtractable.
- * @param lhs The left-hand side of the subtraction
- * @param rhs The right-hand side of the subtraction
- * @return a new instance of the same nt::new_type
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator-(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(
@@ -474,15 +384,6 @@ namespace nt
return {lhs.decay() - rhs.decay()};
}
- /**
- * @brief Subtract two instances of the same nt::new_type, modifying the left-hand side
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is subtractable.
- * @param lhs The left-hand side of the subtractition
- * @param rhs The right-hand side of the subtractition
- * @return a reference to the the modified value
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator-=(new_type<BaseType, TagType, DerivationClause> & lhs,
@@ -494,15 +395,6 @@ namespace nt
return lhs;
}
- /**
- * @brief Multiply two instances of the same nt::new_type
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is multipliable.
- * @param lhs The left-hand side of the multiplication
- * @param rhs The right-hand side of the multiplication
- * @return a new instance of the same nt::new_type
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator*(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(
@@ -512,15 +404,6 @@ namespace nt
return {lhs.decay() * rhs.decay()};
}
- /**
- * @brief Multiply two instances of the same nt::new_type, modifying the left-hand side
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is multiplyable.
- * @param lhs The left-hand side of the multiplication
- * @param rhs The right-hand side of the multiplication
- * @return a reference to the the modified value
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator*=(new_type<BaseType, TagType, DerivationClause> & lhs,
@@ -532,15 +415,6 @@ namespace nt
return lhs;
}
- /**
- * @brief Divide two instances of the same nt::new_type
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is dividable.
- * @param lhs The left-hand side of the division
- * @param rhs The right-hand side of the division
- * @return a new instance of the same nt::new_type
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr
operator/(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(
@@ -550,15 +424,6 @@ namespace nt
return {lhs.decay() / rhs.decay()};
}
- /**
- * @brief Divide two instances of the same nt::new_type, modifying the left-hand side
- *
- * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
- * type is dividable.
- * @param lhs The left-hand side of the division
- * @param rhs The right-hand side of the division
- * @return a reference to the the modified value
- */
template<typename BaseType, typename TagType, auto DerivationClause>
auto constexpr operator/=(new_type<BaseType, TagType, DerivationClause> & lhs,
new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_divide_assignable_v<BaseType>)
@@ -569,6 +434,102 @@ namespace nt
return lhs;
}
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr begin(new_type<BaseType, TagType, DerivationClause> & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_begin_v<BaseType>,
+ typename new_type<BaseType, TagType, DerivationClause>::iterator>
+ {
+ return begin(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr begin(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_begin_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_iterator>
+ {
+ return begin(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr cbegin(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_cbegin_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_iterator>
+ {
+ return cbegin(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rbegin_v<BaseType>,
+ typename new_type<BaseType, TagType, DerivationClause>::reverse_iterator>
+ {
+ return rbegin(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rbegin_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator>
+ {
+ return rbegin(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr crbegin(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_crbegin_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator>
+ {
+ return crbegin(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr end(new_type<BaseType, TagType, DerivationClause> & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_end_v<BaseType>,
+ typename new_type<BaseType, TagType, DerivationClause>::iterator>
+ {
+ return end(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr end(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_end_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_iterator>
+ {
+ return end(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr cend(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_cend_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_iterator>
+ {
+ return cend(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr rend(new_type<BaseType, TagType, DerivationClause> & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rend_v<BaseType>,
+ typename new_type<BaseType, TagType, DerivationClause>::reverse_iterator>
+ {
+ return rend(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr rend(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rend_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator>
+ {
+ return rend(obj.m_value);
+ }
+
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr crend(new_type<BaseType, TagType, DerivationClause> const & obj)
+ -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_crend_v<BaseType const>,
+ typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator>
+ {
+ return crend(obj.m_value);
+ }
+
} // namespace nt
namespace std
diff --git a/include/newtype/version.hpp b/include/newtype/version.hpp
index b2dd19b..8678514 100644
--- a/include/newtype/version.hpp
+++ b/include/newtype/version.hpp
@@ -13,9 +13,9 @@ namespace nt
char const * const name;
} version{
.major = 1,
- .minor = 0,
- .patch = 2,
- .name = "Francesca",
+ .minor = 1,
+ .patch = 0,
+ .name = "Anastasia",
};
} // namespace nt
diff --git a/test/include/iterable_suite.hpp b/test/include/iterable_suite.hpp
new file mode 100644
index 0000000..c2bbc6e
--- /dev/null
+++ b/test/include/iterable_suite.hpp
@@ -0,0 +1,11 @@
+#ifndef NEWTYPE_TEST_ITERABLE_SUITE_HPP
+#define NEWTYPE_TEST_ITERABLE_SUITE_HPP
+
+#include <cute/cute_suite.h>
+
+#include <string>
+#include <utility>
+
+auto iterable_suite() -> std::pair<cute::suite, std::string>;
+
+#endif \ No newline at end of file
diff --git a/test/src/driver.cpp b/test/src/driver.cpp
index cfd6b90..a0e8904 100644
--- a/test/src/driver.cpp
+++ b/test/src/driver.cpp
@@ -4,6 +4,7 @@
#include "equality_comparison_suite.hpp"
#include "hash_suite.hpp"
#include "io_operators_suite.hpp"
+#include "iterable_suite.hpp"
#include "new_type_constructor_suite.hpp"
#include "relational_operators_suite.hpp"
@@ -61,6 +62,7 @@ int main(int argc, char ** argv)
io_operators_suite(),
arithmetic_suite(),
hash_suite(),
+ iterable_suite(),
};
auto selectors = get_test_selectors(suites);
diff --git a/test/src/iterable_suite.cpp b/test/src/iterable_suite.cpp
new file mode 100644
index 0000000..3b46024
--- /dev/null
+++ b/test/src/iterable_suite.cpp
@@ -0,0 +1,719 @@
+#include "iterable_suite.hpp"
+
+#include "kawaii.hpp"
+#include "newtype/derivable.hpp"
+#include "newtype/deriving.hpp"
+#include "newtype/impl/type_traits_extensions.hpp"
+#include "newtype/new_type.hpp"
+
+#include <cute/cute.h>
+
+#include <algorithm>
+#include <array>
+#include <iterator>
+#include <numeric>
+
+namespace
+{
+
+ struct with_member
+ {
+ using iterator = char *;
+ using const_iterator = char const *;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ auto begin() -> iterator;
+ auto begin() const -> const_iterator;
+ auto cbegin() const -> const_iterator;
+ auto rbegin() -> reverse_iterator;
+ auto rbegin() const -> const_reverse_iterator;
+ auto crbegin() const -> const_reverse_iterator;
+
+ auto end() -> iterator;
+ auto end() const -> const_iterator;
+ auto cend() const -> const_iterator;
+ auto rend() -> reverse_iterator;
+ auto rend() const -> const_reverse_iterator;
+ auto crend() const -> const_reverse_iterator;
+ };
+
+ struct with_free
+ {
+ using iterator = char *;
+ using const_iterator = char const *;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ };
+
+ auto begin(with_free &) -> with_free::iterator
+ {
+ return {};
+ }
+
+ auto begin(with_free const &) -> with_free::const_iterator
+ {
+ return {};
+ }
+
+ auto cbegin(with_free const &) -> with_free::const_iterator
+ {
+ return {};
+ }
+
+ auto rbegin(with_free &) -> with_free::reverse_iterator
+ {
+ return {};
+ }
+
+ auto rbegin(with_free const &) -> with_free::const_reverse_iterator
+ {
+ return {};
+ }
+
+ auto crbegin(with_free const &) -> with_free::const_reverse_iterator
+ {
+ return {};
+ }
+
+ auto end(with_free &) -> with_free::iterator
+ {
+ return {};
+ }
+
+ auto end(with_free const &) -> with_free::const_iterator
+ {
+ return {};
+ }
+
+ auto cend(with_free const &) -> with_free::const_iterator
+ {
+ return {};
+ }
+
+ auto rend(with_free &) -> with_free::reverse_iterator
+ {
+ return {};
+ }
+
+ auto rend(with_free const &) -> with_free::const_reverse_iterator
+ {
+ return {};
+ }
+
+ auto crend(with_free const &) -> with_free::const_reverse_iterator
+ {
+ return {};
+ }
+
+} // namespace
+
+inline namespace combined_enablement_tests
+{
+
+ auto a_new__type_not_deriving_iterable_has_no_begin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_begin_v<type_alias>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_constant_begin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_begin_v<type_alias const>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_cbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_cbegin_v<type_alias>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_rbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_rbegin_v<type_alias>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_constant_rbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_rbegin_v<type_alias const>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_crbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_crbegin_v<type_alias>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_end() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_end_v<type_alias>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_constant_end() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_end_v<type_alias const>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_cend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_cend_v<type_alias>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_rend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_rend_v<type_alias>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_constant_rend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_rend_v<type_alias const>));
+ }
+
+ auto a_new__type_not_deriving_iterable_has_no_crend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::has_crend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_begin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_begin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_begin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_begin_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_cbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_rbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_rbegin_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crbegin() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_crbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_end() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_end_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_end() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_end_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_cend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_rend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_rend_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crend() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_crend_v<type_alias>));
+ }
+
+} // namespace combined_enablement_tests
+
+inline namespace member_enablement_tests
+{
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_begin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_begin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_begin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_begin_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_cbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_rbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_rbegin_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_crbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_end() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_end_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_end() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_end_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_cend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_rend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_rend_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_member_crend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_begin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_begin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_begin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_begin_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_cbegin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_rbegin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_rbegin_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_crbegin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_end() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_end_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_end() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_end_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_cend_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_rend_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_rend_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_member_crend_v<type_alias>);
+ }
+
+} // namespace member_enablement_tests
+
+inline namespace free_enablement_tests
+{
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_begin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_begin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_begin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_begin_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_cbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_rbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_rbegin_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crbegin() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_crbegin_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_end() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_end_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_end() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_end_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_cend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_rend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_rend_v<type_alias const>));
+ }
+
+ auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crend() -> void
+ {
+ using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>;
+ ASSERT(!(nt::impl::has_free_crend_v<type_alias>));
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_begin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_begin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_begin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_begin_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_cbegin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_rbegin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_rbegin_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crbegin() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_crbegin_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_end() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_end_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_end() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_end_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_cend_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_rend_v<type_alias>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_rend_v<type_alias const>);
+ }
+
+ auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crend() -> void
+ {
+ using type_alias = nt::new_type<with_free, struct tag, deriving(nt::Iterable)>;
+ ASSERT(nt::impl::has_free_crend_v<type_alias>);
+ }
+
+} // namespace free_enablement_tests
+
+inline namespace semantic_tests
+{
+
+ auto a_non_const_object_of_iterable_new__type_can_be_used_in_value_range_for() -> void
+ {
+ using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>;
+ auto object = type_alias{{1, 2, 3}};
+ for (auto e : object)
+ {
+ (void)e;
+ }
+ ASSERT(true);
+ }
+
+ auto a_const_object_of_iterable_new__type_can_be_used_in_value_range_for() -> void
+ {
+ using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>;
+ auto const object = type_alias{{1, 2, 3}};
+ for (auto e : object)
+ {
+ (void)e;
+ }
+ ASSERT(true);
+ }
+
+ auto a_non_const_object_of_iterable_new__type_can_be_used_in_reference_range_for() -> void
+ {
+ using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>;
+ auto object = type_alias{{1, 2, 3}};
+ for (auto & e : object)
+ {
+ (void)e;
+ }
+ ASSERT(true);
+ }
+
+ auto a_const_object_of_iterable_new__type_can_be_used_in_const_reference_range_for() -> void
+ {
+ using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>;
+ auto const object = type_alias{{1, 2, 3}};
+ for (auto const & e : object)
+ {
+ (void)e;
+ }
+ ASSERT(true);
+ }
+
+ auto applying_accumulate_to_an_interable_new__type_yields_the_same_result_as_when_applied_to_the_base_type() -> void
+ {
+ using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>;
+ auto const nt_object = type_alias{{1, 2, 3}};
+ auto const bt_object = type_alias::base_type{1, 2, 3};
+
+ auto nt_result = std::accumulate(std::cbegin(nt_object), std::cend(nt_object), 0);
+ auto bt_result = std::accumulate(std::cbegin(bt_object), std::cend(bt_object), 0);
+
+ ASSERT_EQUAL(bt_result, nt_result);
+ }
+
+ auto iterating_over_an_iterable_new__type_yields_the_elements_in_the_same_order_as_when_iterating_the_base_type() -> void
+ {
+ using std::cbegin, std::cend, std::equal;
+ using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>;
+ auto const nt_object = type_alias{{1, 2, 3}};
+ auto const bt_object = type_alias::base_type{1, 2, 3};
+
+ ASSERT(equal(cbegin(nt_object), cend(nt_object), cbegin(bt_object), cend(bt_object)));
+ }
+
+} // namespace semantic_tests
+
+auto iterable_suite() -> std::pair<cute::suite, std::string>
+{
+ return {{
+ /// Combined Enablement Tests
+ KAWAII(a_new__type_not_deriving_iterable_has_no_begin),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_constant_begin),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_cbegin),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_rbegin),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_constant_rbegin),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_crbegin),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_end),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_constant_end),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_cend),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_rend),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_constant_rend),
+ KAWAII(a_new__type_not_deriving_iterable_has_no_crend),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_begin),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_begin),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cbegin),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rbegin),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rbegin),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crbegin),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_end),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_end),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cend),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rend),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rend),
+ KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crend),
+
+ /// Member Enablement Tests
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_begin),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_begin),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cbegin),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rbegin),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rbegin),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crbegin),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_end),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_end),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cend),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rend),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rend),
+ KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crend),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_begin),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_begin),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cbegin),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rbegin),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rbegin),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crbegin),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_end),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_end),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cend),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rend),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rend),
+ KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crend),
+
+ /// Free Enablement Tests
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_begin),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_begin),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cbegin),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rbegin),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rbegin),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crbegin),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_end),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_end),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cend),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rend),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rend),
+ KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crend),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_begin),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_begin),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cbegin),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rbegin),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rbegin),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crbegin),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_end),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_end),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cend),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rend),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rend),
+ KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crend),
+
+ /// Semantic Tests
+ KAWAII(a_non_const_object_of_iterable_new__type_can_be_used_in_value_range_for),
+ KAWAII(a_const_object_of_iterable_new__type_can_be_used_in_value_range_for),
+ KAWAII(a_non_const_object_of_iterable_new__type_can_be_used_in_reference_range_for),
+ KAWAII(a_const_object_of_iterable_new__type_can_be_used_in_const_reference_range_for),
+ KAWAII(applying_accumulate_to_an_interable_new__type_yields_the_same_result_as_when_applied_to_the_base_type),
+ KAWAII(iterating_over_an_iterable_new__type_yields_the_elements_in_the_same_order_as_when_iterating_the_base_type),
+ },
+
+ "Iterable Tests"};
+} \ No newline at end of file
diff --git a/test_package/.gitignore b/test_package/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/test_package/.gitignore
@@ -0,0 +1 @@
+/build \ No newline at end of file
diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt
new file mode 100644
index 0000000..1aafacf
--- /dev/null
+++ b/test_package/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION "3.0")
+
+project("TestPackage" CXX)
+
+set(CMAKE_CXX_STANDARD "20")
+
+include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
+conan_basic_setup()
+
+add_executable("test_package" "main.cpp") \ No newline at end of file
diff --git a/test_package/conanfile.py b/test_package/conanfile.py
new file mode 100644
index 0000000..0b12b5f
--- /dev/null
+++ b/test_package/conanfile.py
@@ -0,0 +1,17 @@
+import os
+from conans import ConanFile, CMake
+
+
+class NewtypeTestConan(ConanFile):
+ settings = None
+ requires = "newtype/[~=1.0]@fmorgner/stable"
+ generators = "cmake"
+
+ def build(self):
+ cmake = CMake(self)
+ cmake.configure()
+ cmake.build()
+
+ def test(self):
+ os.chdir("bin")
+ self.run(".%stest_package" % os.sep) \ No newline at end of file
diff --git a/test_package/main.cpp b/test_package/main.cpp
new file mode 100644
index 0000000..95fe763
--- /dev/null
+++ b/test_package/main.cpp
@@ -0,0 +1,11 @@
+#include "newtype/new_type.hpp"
+
+#include <iostream>
+
+using Integer = nt::new_type<int, struct IntegerTag, deriving(nt::Show)>;
+
+auto main() -> int
+{
+ auto n = Integer{42};
+ std::cout << "n == " << n.decay() << '\n';
+} \ No newline at end of file