From 0c258f2d8cc175468adf19cb88c3354f7caa2357 Mon Sep 17 00:00:00 2001 From: Will Wray Date: Tue, 3 May 2022 19:18:53 -0400 Subject: [PATCH] Add tupl_dev dir and move codegen & tests there Focus on simple usage; provide tupl_impl.hpp so no codegen is needed. The main directory was cluttered with codegen sources and the builds eagerly ran codegen preprocessing and all tests, unnecessary for use. Add a tupl_dev directory and move codegen sources and tests there. A developer can run codegen there to create a tupl_dev/tupl_impl.hpp that overrides the main directory file. Remove the CMake developer preset; it only complicates things. --- CMakeLists.txt | 119 ++-- CMakePresets.json | 35 - meson.build | 44 +- tupl.hpp | 61 +- tupl_dev/CMakeLists.txt | 108 ++++ tupl_dev/meson.build | 35 + namespace.hpp => tupl_dev/namespace.hpp | 0 {tests => tupl_dev/tests}/CMakeLists.txt | 0 {tests => tupl_dev/tests}/tupl_test.cpp | 27 + .../tupl_impl_noedit_warn.hpp | 0 .../tupl_impl_pre.hpp | 24 +- tupl_impl.hpp | 597 ++++++++++++++++++ whats_tupl_docs.svg | 23 - 13 files changed, 855 insertions(+), 218 deletions(-) delete mode 100644 CMakePresets.json create mode 100644 tupl_dev/CMakeLists.txt create mode 100644 tupl_dev/meson.build rename namespace.hpp => tupl_dev/namespace.hpp (100%) rename {tests => tupl_dev/tests}/CMakeLists.txt (100%) rename {tests => tupl_dev/tests}/tupl_test.cpp (80%) rename tupl_impl_noedit_warn.hpp => tupl_dev/tupl_impl_noedit_warn.hpp (100%) rename tupl_impl_pre.hpp => tupl_dev/tupl_impl_pre.hpp (94%) create mode 100644 tupl_impl.hpp delete mode 100644 whats_tupl_docs.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index fed606f..a0d853d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 3.15) +# Contents generated by 'cmake-init -h', manually edited to a standalone +# single file, with includes expanded inline + if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) message( FATAL_ERROR @@ -11,28 +14,19 @@ endif() project( tupl - VERSION 0.2.0 + VERSION 0.3.0 DESCRIPTION "C++20 aggregate tuple" - HOMEPAGE_URL "https://github.com/willwray/tupl" + HOMEPAGE_URL "https://github.com/Lemurian-Labs/tupl" LANGUAGES CXX ) -# This variable is set by project() in CMake 3.21+ +# PROJECT_IS_TOP_LEVEL variable is set by project() in CMake 3.21+ string( COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}" PROJECT_IS_TOP_LEVEL ) -# ---- Developer mode ---- - -# Developer mode enables targets and paths only relevant for developers. -# Targets needed to build the project must be provided unconditionally, -# so consumers can trivially build and package the project -if(PROJECT_IS_TOP_LEVEL) - option(tupl_DEVELOPER_MODE "Enable developer mode" OFF) -endif() - # ---- Warning guard ---- # target_include_directories with SYSTEM modifier requests the compiler @@ -52,18 +46,10 @@ if(NOT PROJECT_IS_TOP_LEVEL) endif() endif() -# ---- Fetch dependencies; c_array_support & IREPEAT (for codegen) ---- +# ---- Fetch dependency; c_array_support (for C array members) ---- include(FetchContent) -FetchContent_Declare( - irepeat - GIT_REPOSITORY https://github.com/willwray/IREPEAT - GIT_TAG v0.3 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" -) - FetchContent_Declare( c_array_support GIT_REPOSITORY https://github.com/willwray/c_array_support @@ -72,13 +58,8 @@ FetchContent_Declare( BUILD_COMMAND "" ) -FetchContent_MakeAvailable(irepeat) - FetchContent_MakeAvailable(c_array_support) -add_library(irepeat INTERFACE) -target_include_directories(irepeat INTERFACE ${irepeat_SOURCE_DIR}/) - add_library(c_array_support INTERFACE) target_include_directories( c_array_support INTERFACE ${c_array_support_SOURCE_DIR}/) @@ -88,18 +69,15 @@ target_include_directories( add_library(tupl_tupl INTERFACE) add_library(tupl::tupl ALIAS tupl_tupl) -target_link_libraries(tupl_tupl INTERFACE irepeat c_array_support) - set_property( TARGET tupl_tupl PROPERTY EXPORT_NAME tupl ) target_include_directories( - tupl_tupl ${tupl_warning_guard} + tupl_tupl INTERFACE "$" - "$" ) target_compile_features(tupl_tupl INTERFACE cxx_std_20) @@ -107,79 +85,68 @@ target_compile_features(tupl_tupl INTERFACE cxx_std_20) # ---- Install rules ---- if(NOT CMAKE_SKIP_INSTALL_RULES) +# include(cmake/install-rules.cmake) +# install-rules.cmake - BEGIN --------------------- if(PROJECT_IS_TOP_LEVEL) - set(CMAKE_INSTALL_INCLUDEDIR tupl CACHE PATH "") + set(CMAKE_INSTALL_INCLUDEDIR include/tupl CACHE PATH "") endif() - #include(CMakePackageConfigHelpers) - #include(GNUInstallDirs) - + # Project is configured with no languages, so tell GNUInstallDirs the lib dir + set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "") + + include(CMakePackageConfigHelpers) + include(GNUInstallDirs) + # find_package() call for consumers to find this project set(package tupl) install( - DIRECTORY . + DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT tupl_Development ) - #install( - # TARGETS tupl_tupl - # EXPORT tuplTargets - # INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - #) - - #write_basic_package_version_file( - # "${package}ConfigVersion.cmake" - # COMPATIBILITY SameMajorVersion - # ARCH_INDEPENDENT - #) - - # Allow package maintainers to override the path for the configs + install( + TARGETS tupl_tupl + EXPORT tuplTargets + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) + + write_basic_package_version_file( + "${package}ConfigVersion.cmake" + COMPATIBILITY SameMajorVersion + ARCH_INDEPENDENT + ) + + # Allow package maintainers to freely override the path for the configs set( tupl_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}" - CACHE PATH "CMake package config location relative to the " - "install prefix" + CACHE PATH "CMake package config location relative to the install prefix" ) mark_as_advanced(tupl_INSTALL_CMAKEDIR) - + install( FILES cmake/install-config.cmake DESTINATION "${tupl_INSTALL_CMAKEDIR}" RENAME "${package}Config.cmake" COMPONENT tupl_Development ) - + install( FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake" DESTINATION "${tupl_INSTALL_CMAKEDIR}" COMPONENT tupl_Development ) - - #install( - # EXPORT tuplTargets - # NAMESPACE tupl:: - # DESTINATION "${tupl_INSTALL_CMAKEDIR}" - # COMPONENT tupl_Development - #) - - if(PROJECT_IS_TOP_LEVEL) - include(CPack) - endif() -endif() - -# ---- Developer mode ---- -if(NOT tupl_DEVELOPER_MODE) - return() -elseif(NOT PROJECT_IS_TOP_LEVEL) - message( - AUTHOR_WARNING - "Developer mode is intended for developers of tupl" + install( + EXPORT tuplTargets + NAMESPACE tupl:: + DESTINATION "${tupl_INSTALL_CMAKEDIR}" + COMPONENT tupl_Development ) -endif() -include(CTest) -if(BUILD_TESTING) - add_subdirectory(tests) + if(PROJECT_IS_TOP_LEVEL) + include(CPack) + endif() +# - install-rules.cmake - BEGIN --------------------- endif() diff --git a/CMakePresets.json b/CMakePresets.json deleted file mode 100644 index dd310c5..0000000 --- a/CMakePresets.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "version": 1, - "cmakeMinimumRequired": { - "major": 3, - "minor": 15, - "patch": 0 - }, - "configurePresets": [ - { - "name": "dev-mode", - "displayName": "Developer mode", - "description": "Developer build using Ninja generator", - "generator": "Ninja", - "binaryDir": "${sourceDir}/dev", - "cacheVariables": { - "tupl_DEVELOPER_MODE": "ON" - } - }, - { - "name": "flags-unix", - "hidden": true, - "cacheVariables": { - "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic", - "CMAKE_CXX_EXTENSIONS": "OFF" - } - }, - { - "name": "flags-windows", - "hidden": true, - "cacheVariables": { - "CMAKE_CXX_FLAGS": "/W4 /permissive- /utf-8 /volatile:iso /EHsc /Zc:__cplusplus /Zc:throwingNew" - } - } - ] -} diff --git a/meson.build b/meson.build index 1f6b3ac..3734526 100644 --- a/meson.build +++ b/meson.build @@ -1,45 +1,15 @@ project('tupl', 'cpp', - default_options : ['warning_level=3'], - version : '0.1' + default_options : ['cpp_std=c++20'], + version : '0.3' ) c_array_support_dep = subproject('c_array_support').get_variable('c_array_support_dep') -IREPEAT_dep = subproject('IREPEAT').get_variable('IREPEAT_dep') - -compiler_id = meson.get_compiler('cpp').get_id() - -if compiler_id == 'msvc' or compiler_id == 'clang-cl' - extra_args = ['/std:c++latest','/Zc:preprocessor'] - prepro_args = ['/std:c++latest','/Zc:preprocessor','/I.','-I..','/I..\subprojects\IREPEAT','/C','/EP','/TP','/P'] - output_flag = '/Fi' -elif compiler_id == 'clang' - extra_args = ['-std=c++20'] - prepro_args = ['-I.','-I..','-I../subprojects/IREPEAT','-MMD','-nostdinc','-C','-E','-P','-Wno-c++20-compat'] - output_flag = '-o' -else - extra_args = ['-std=c++20'] - prepro_args = ['-I.','-I..','-I../subprojects/IREPEAT','-MMD','-nostdinc','-C','-E','-P'] - output_flag = '-o' -endif - -tupl_impl_header = custom_target('tupl_impl.hpp', - input: 'tupl_impl_pre.hpp', - output: 'tupl_impl.hpp', - command: [meson.get_compiler('cpp').cmd_array(), prepro_args, output_flag+'@OUTPUT@', '@INPUT@'], - depfile: 'tupl_impl.d', - install: true, - install_dir: meson.source_root() -) tupl_dep = declare_dependency( - dependencies: [c_array_support_dep, IREPEAT_dep], + dependencies: [c_array_support_dep], include_directories : include_directories('.'), - compile_args : extra_args, - sources : [tupl_impl_header] -).partial_dependency(includes: true, compile_args: true, sources: true) - -test('test tupl', - executable('test_tupl', 'tests/tupl_test.cpp', - dependencies: [c_array_support_dep, IREPEAT_dep, tupl_dep] - ) ) + +IREPEAT_dep = subproject('IREPEAT').get_variable('IREPEAT_dep') + +subdir('tupl_dev') diff --git a/tupl.hpp b/tupl.hpp index bc7da11..7acf7d8 100644 --- a/tupl.hpp +++ b/tupl.hpp @@ -1,45 +1,30 @@ -// Copyright (c) 2021 Will Wray https://keybase.io/willwray +// Copyright (c) 2022 Lemurian Labs https://lemurianlabs.com/ // // Distributed under the Boost Software License, Version 1.0. // http://www.boost.org/LICENSE_1_0.txt // -// Repo: https://github.com/willwray/tupl +// Repo: https://github.com/Lemurian-Labs/tupl -#ifndef TUPL_HPP -#define TUPL_HPP +#ifndef LML_TUPL_HPP +#define LML_TUPL_HPP /* - ltl::tupl - -=========- + tupl + ========== + tupl is a C++20 tuple type implemented as struct specializations + for a variadic number of members T... up to 16 as provided. + + DO NOT EDIT the file 'tupl_impl.hpp'. + The implementation in tupl_impl.hpp is generated by preprocessing + the file tupl_dev/tupl_impl_pre.hpp; edit this if you need to. + If more members are needed then follow instructions in tupl_dev + to generate a file tupl_dev/tupl_impl.hpp - A C++20 tuple type implemented as aggregate struct specializations. - Configured by default for up to 16 members of any allowed type. - - Depends on for assignable_from, ranges::swap CPO, etc. - Depends on for three-way operator <=> comparisons, etc. + Depends on for assignable_from, ranges::swap CPO, etc. + Depends on for three-way operator <=> comparisons, etc. (MSVC implementation also depends on for uintptr_t.) - The macro implementation in "tupl_impl_pre.hpp" should be preprocessed - on installation to generate "tupl_impl.hpp" header, but not obligatory; - if tupl_impl.hpp header isn't found on the include search paths then - tupl_impl_pre.hpp is used instead (it may give worse error messages). - - You can manually preprocess tupl_impl_pre.hpp -> tupl_impl.hpp - with a command line like: - - > cc -I./subprojects/IREPEAT -MMD -C -E -P -o tupl_impl.hpp - tupl_impl_pre.hpp - - > cl /I:../subprojects/IREPEAT /Zc:preprocessor /C /EP - - Requires __VA_OPT__ preprocessor support (MSVC cl /Zc:preprocessor) - lack of __VA_OPT__ is auto-detected via a static_assert error message. - (other useful cpp flags are -nostdinc -Wno-c++20-compat) - - Namespace id 'ltl' and class template id 'tupl' are configurable via - NAMESPACE_ID and TUPL_ID defines. The arity is also configurable. - - E.g. to generate ns::tuple add -DNAMESPACE_ID=ns -DTUPL_ID=tuple, - or to generate with no namespace -DNAMESPACE_ID= + Depends on lml c_array_support project for generic support of array + member comparison and assignment, alongside other regular types. */ #include "array_compare.hpp" @@ -59,11 +44,13 @@ concept same_ish = std::same_as>; #define UNREACHABLE() #endif -#if __has_include("tupl_impl.hpp") -#include "tupl_impl.hpp" // Do not edit generated file "tupl_impl.hpp" +// The header "tupl_impl.hpp" as provided is limited to 'arity' 16. +// If tupl_dev/tupl_impl.hpp exists then is included instead. +// +#if __has_include("tupl_dev/tupl_impl.hpp") +#include "tupl_dev/tupl_impl.hpp" #else -#include "tupl_impl_pre.hpp" // If you edit "tupl_impl_pre.hpp" then - // remember to regenerate "tupl_impl.hpp" +#include "tupl_impl.hpp" #endif #undef UNREACHABLE diff --git a/tupl_dev/CMakeLists.txt b/tupl_dev/CMakeLists.txt new file mode 100644 index 0000000..49b566a --- /dev/null +++ b/tupl_dev/CMakeLists.txt @@ -0,0 +1,108 @@ +cmake_minimum_required(VERSION 3.15) + +# Contents generated by 'cmake-init -h', manually edited to a standalone +# single file, with includes expanded inline + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message( + FATAL_ERROR + "In-source builds are not supported. " + "Make a new directory (e.g., 'build'), and run CMake from there. " + "You may need to delete 'CMakeCache.txt' and 'CMakeFiles/' first." + ) +endif() + +project( + tupl_dev + VERSION 0.3.0 + DESCRIPTION "Code generation for tupl project" + LANGUAGES CXX +) + +# PROJECT_IS_TOP_LEVEL variable is set by project() in CMake 3.21+ +string( + COMPARE EQUAL + "${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}" + PROJECT_IS_TOP_LEVEL +) + +# ---- Fetch dependency; IREPEAT (for codegen) ---- + +include(FetchContent) + +FetchContent_Declare( + irepeat + GIT_REPOSITORY https://github.com/willwray/IREPEAT + GIT_TAG v0.3 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" +) + +FetchContent_MakeAvailable(irepeat) + +add_library(irepeat INTERFACE) +target_include_directories(irepeat INTERFACE ${irepeat_SOURCE_DIR}/) + +# ---- Install rules ---- + +if(NOT CMAKE_SKIP_INSTALL_RULES) + if(PROJECT_IS_TOP_LEVEL) + set(CMAKE_INSTALL_INCLUDEDIR tupl CACHE PATH "") + endif() + + #include(CMakePackageConfigHelpers) + #include(GNUInstallDirs) + + # find_package() call for consumers to find this project + set(package tupl) + + install( + DIRECTORY . + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT tupl_Development + ) + + #install( + # TARGETS tupl_tupl + # EXPORT tuplTargets + # INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + #) + + #write_basic_package_version_file( + # "${package}ConfigVersion.cmake" + # COMPATIBILITY SameMajorVersion + # ARCH_INDEPENDENT + #) + + # Allow package maintainers to override the path for the configs + set( + tupl_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}" + CACHE PATH "CMake package config location relative to the " + "install prefix" + ) + mark_as_advanced(tupl_INSTALL_CMAKEDIR) + + install( + FILES cmake/install-config.cmake + DESTINATION "${tupl_INSTALL_CMAKEDIR}" + RENAME "${package}Config.cmake" + COMPONENT tupl_Development + ) + + install( + FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake" + DESTINATION "${tupl_INSTALL_CMAKEDIR}" + COMPONENT tupl_Development + ) + + #install( + # EXPORT tuplTargets + # NAMESPACE tupl:: + # DESTINATION "${tupl_INSTALL_CMAKEDIR}" + # COMPONENT tupl_Development + #) + + if(PROJECT_IS_TOP_LEVEL) + include(CPack) + endif() +endif() diff --git a/tupl_dev/meson.build b/tupl_dev/meson.build new file mode 100644 index 0000000..36bd77d --- /dev/null +++ b/tupl_dev/meson.build @@ -0,0 +1,35 @@ +compiler_id = meson.get_compiler('cpp').get_id() + +if compiler_id == 'msvc' or compiler_id == 'clang-cl' + prepro_args = ['/std:c++latest','/Zc:preprocessor','/I.','-I..','/I..\subprojects\IREPEAT','/C','/EP','/TP','/P'] + output_flag = '/Fi' +elif compiler_id == 'clang' + prepro_args = ['-I.','-I..','-I../subprojects/IREPEAT','-MMD','-nostdinc','-C','-E','-P','-Wno-c++20-compat'] + output_flag = '-o' +else + prepro_args = ['-I.','-I..','-I../subprojects/IREPEAT','-MMD','-nostdinc','-C','-E','-P'] + output_flag = '-o' +endif + +tupl_impl_header = custom_target( + input: 'tupl_impl_pre.hpp', + output: 'tupl_impl.hpp', + command: [meson.get_compiler('cpp').cmd_array(), + get_option('cpp_args'), + prepro_args, output_flag+'@OUTPUT@', '@INPUT@'], + depfile: 'tupl_impl.d', + install: true, + install_dir: meson.current_source_dir() +) + +tupl_dev_dep = declare_dependency( + dependencies: [IREPEAT_dep], + include_directories : include_directories('.'), + sources : [tupl_impl_header] +) + +test('test tupl', + executable('test_tupl', 'tests/tupl_test.cpp', + dependencies: [c_array_support_dep, tupl_dep] + ) +) diff --git a/namespace.hpp b/tupl_dev/namespace.hpp similarity index 100% rename from namespace.hpp rename to tupl_dev/namespace.hpp diff --git a/tests/CMakeLists.txt b/tupl_dev/tests/CMakeLists.txt similarity index 100% rename from tests/CMakeLists.txt rename to tupl_dev/tests/CMakeLists.txt diff --git a/tests/tupl_test.cpp b/tupl_dev/tests/tupl_test.cpp similarity index 80% rename from tests/tupl_test.cpp rename to tupl_dev/tests/tupl_test.cpp index 30b79e8..d7e4316 100644 --- a/tests/tupl_test.cpp +++ b/tupl_dev/tests/tupl_test.cpp @@ -4,6 +4,10 @@ using namespace ltl; +struct derived_tupl : tupl {}; +static_assert( tuplish ); +static_assert(! tuplish ); + template constexpr std::add_const_t& as_const(T& t) noexcept { return t; } @@ -116,6 +120,29 @@ void big() { //br = {(BIG const&)bc}; // disambiguated - exact match // assert( ) } +struct Ex { void f() const; }; +using F = void()const; +F Ex::* fmp = &Ex::f; + +tupl tup = {"c++",true}; // deduces tupl +auto& tup_copy_assign(char(&cstr)[4],bool b) +{ + return tup = ltl::tie(cstr,b); // copies char[4] and bool +} +using Tup = decltype(tup); + +static_assert( std::is_same_v< Tup, tupl> + && std::is_aggregate_v< Tup > + && std::is_standard_layout_v< Tup > + && std::is_trivial_v< Tup > + && std::is_trivially_copyable_v< Tup > +); +template struct structural; +using is_structural = structural<{"tupl"}>; + +auto ass = []{ + tup = {"c--",false}; // copy-assigns char[4] and bool +}; int main() { diff --git a/tupl_impl_noedit_warn.hpp b/tupl_dev/tupl_impl_noedit_warn.hpp similarity index 100% rename from tupl_impl_noedit_warn.hpp rename to tupl_dev/tupl_impl_noedit_warn.hpp diff --git a/tupl_impl_pre.hpp b/tupl_dev/tupl_impl_pre.hpp similarity index 94% rename from tupl_impl_pre.hpp rename to tupl_dev/tupl_impl_pre.hpp index b9dd972..9acc7a2 100644 --- a/tupl_impl_pre.hpp +++ b/tupl_dev/tupl_impl_pre.hpp @@ -54,13 +54,15 @@ TUPL_ID(E&&...) -> TUPL_ID...>; template TUPL_ID(T(&&)[N], E&&...) -> tupl...>; // - +//template auto to_tupl(Tconst&) -> TUPL_ID; +//template using to_tupl = decltype(as_tupl(std::declval())); // is_tupl trait -template inline constexpr bool is_tupl = false; -template inline constexpr bool is_tupl> = true; +//template inline constexpr bool is_tupl = false; +//template inline constexpr bool is_tupl> = true; // -// tuplish concept -template concept tuplish = is_tupl>; +// tuplish concept, requires a 'tupl_t' member alias +template concept tuplish = std::is_convertible_v::tupl_t>; // tupl_size variable template (unrelated to std::tuple_size) template extern const std::size_t tupl_size; @@ -154,7 +156,8 @@ using tupl_assign_fwd_t = typename tupl_type_map::type; template <> // tupl specializations defined in TUPL_PASS == 1 struct TUPL_ID<> { - using tie_t = TUPL_ID; +// using tie_t = TUPL_ID; + using tupl_t = TUPL_ID; static consteval std::size_t size() noexcept { return {}; } @@ -232,11 +235,11 @@ decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(__VA_ARGS__)))\ { return f(__VA_ARGS__); } #define R_TUPL tupl_assign_fwd_t -#define TUPL_TIE_T tupl_tie_t +//#define TUPL_TIE_T tupl_tie_t #define TUPL_PASS 1 #define VREPEAT_COUNT TUPL_MAX_INDEX -#define VREPEAT_MACRO tupl_impl_pre.hpp +#define VREPEAT_MACRO tupl_dev/tupl_impl_pre.hpp #include "VREPEAT.hpp" #undef TUPL_PASS @@ -248,7 +251,8 @@ decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(__VA_ARGS__)))\ template struct TUPL_ID { - using tie_t = TUPL_TIE_T const; +// using tie_t = TUPL_TIE_T const; + using tupl_t = TUPL_ID; MEMBER_DECLS @@ -269,7 +273,7 @@ struct TUPL_ID requires tupl_tie {return assign_to{*this} = r;} - constexpr auto& operator=(std::same_as auto const& r) const + constexpr auto& operator=(std::same_as> auto const& r) const {return assign_to{*this} = r;} MAP_V(TUPL_t_DATA_FWDS) diff --git a/tupl_impl.hpp b/tupl_impl.hpp new file mode 100644 index 0000000..bae6c04 --- /dev/null +++ b/tupl_impl.hpp @@ -0,0 +1,597 @@ +/* WARNING: Do not edit this file "tupl_impl.hpp" + ======= +* it's generated by preprocessing "tupl_impl_pre.hpp" so is overwritten +* each time the preprocessing step is rerun, preferably automatically. +***********************************************************************/ +/* + Copyright (c) 2021 Will Wray https://keybase.io/willwray + + Distributed under the Boost Software License, Version 1.0. + http://www.boost.org/LICENSE_1_0.txt + + Repo: https://github.com/willwray/tupl +*/ +namespace ltl { // OPEN namespace NAMESPACE_ID +template using DEFAULT_ASSIGNABLE = std::bool_constant< + default_assignable>; +template using THREE_WAY_COMPARABLE = std::bool_constant< + three_way_comparable>; +template using EQUALITY_COMPARABLE = std::bool_constant< + equality_comparable>; +template using MEMBER_DEFAULT_3WAY = std::bool_constant< + member_default_3way>; +template using ASSIGN_OVERLOAD = std::bool_constant< + assignable_from + && ! std::assignable_from>; +inline constexpr std::size_t tupl_max_arity = 0xf +1; +// +// Primary template declaration, requires sizeof...(T) < TUPL_MAX_ARITY +template struct tupl; +// +namespace impl { +// decay_f decay function type (hard fail for abominable functions) +template > +using decay_f = std::conditional_t,U*,U>; +} +// CTAD deduce values including arrays (i.e. no decay, unlike std tuple) +template +tupl(E&&...) -> tupl...>; +// CTAD deduce first argument as an rvalue array from braced init-list +template +tupl(T(&&)[N], E&&...) -> tupl...>; +// +//template auto to_tupl(Tconst&) -> TUPL_ID; +//template using to_tupl = decltype(as_tupl(std::declval())); +// is_tupl trait +//template inline constexpr bool is_tupl = false; +//template inline constexpr bool is_tupl> = true; +// +// tuplish concept, requires a 'tupl_t' member alias +template concept tuplish = std::is_convertible_v::tupl_t>; +// tupl_size variable template (unrelated to std::tuple_size) +template extern const std::size_t tupl_size; +template inline constexpr auto tupl_size> + = sizeof...(U); +// size(): the number of tupl elements as an integral constant +template constexpr auto size() +-> std::integral_constant>> +{ return {}; } +// size(tupl): the number of tupl elements as an integral constant +template constexpr auto size(T const&) +-> std::integral_constant>> +{ return {}; } +// tupl_types_all meta function +template class P> +inline constexpr bool tupl_types_all = false; +// +template class P> +inline constexpr bool tupl_types_all,P> = (P() && ...); +// +// tupl_val concept: tuplish type with all object-type elements +// (note: is_object matches unbounded array T[], allows for FAM) +template +concept tupl_val = tuplish + && tupl_types_all, std::is_object>; +template using is_object_lval_ref = + std::bool_constant< std::is_lvalue_reference() + && std::is_object>()>; +// tupl_tie concept: tuplish type with all reference-to-object elements +// (note: is_object matches unbounded array T[] so T(&)[] is admitted) +template +concept tupl_tie = + tuplish + && ! std::same_as, tupl<>> + && tupl_types_all, is_object_lval_ref>; +// tupl_type_map, map> -> tupl...> +template class, typename> +struct tupl_type_map; +template class M, typename...T> +struct tupl_type_map> { + using type = tupl...>; +}; +// +namespace impl { +template +auto assign_fwd_f() { + using V = std::remove_cvref_t; + if constexpr (std::is_move_assignable_v>) + { + if constexpr (std::is_trivially_copyable_v && !std::is_array_v + && sizeof(V)<=16) + return std::type_identity{}; + else + if constexpr (std::is_lvalue_reference_v || std::is_array_v) + return std::type_identity{}; + else + return std::type_identity{}; + } + else return std::type_identity{}; +} +} +// assign_fwd 'forwarding' carrier type for assignment operator= +// -> void for a non-assignable type (renders it incomplete) +// else V = remove_cvref_t and: +// -> V for trivially_copyable non-array V of 16 bytes or less +// -> V const& for lvalue_ref U or array V (no move for & or array) +// -> V&& otherwise +// (V&& won't accept V&, so either move or const_cast to V const&) +template +using assign_fwd = typename decltype(impl::assign_fwd_f())::type; +// +// +template +using tupl_tie_t = + typename tupl_type_map::type; +// +template +using tupl_assign_fwd_t = typename tupl_type_map::type; +// +// tupl<> zero-size pack specialization +template <> // tupl specializations defined in TUPL_PASS == 1 +struct tupl<> +{ +// using tie_t = TUPL_ID; + using tupl_t = tupl; + static consteval std::size_t size() noexcept { return {}; } + auto operator<=>(tupl const&) const = default; + constexpr decltype(auto) operator()(auto f) const + noexcept(noexcept(f())) { return f(); } +}; +// +template +inline constexpr bool tupls_assignable {}; +template +inline constexpr bool tupls_assignable,tupl> = + (assignable_from && ...); +// customization for tuple-tuple assignment +template +struct assign_to +{ + using L = std::remove_cvref_t; + using value_type = std::conditional_t, L, const L>; + value_type& l; + template + requires (tupls_assignable>) + constexpr value_type& operator=(R&& r) const noexcept( + std::is_reference_v + ? tupl_types_all // array R? + : tupl_types_all)// array R? + { + map(l, [&r](auto&...t) { + map(r, [&t...](auto&...u) { + if constexpr (std::is_reference_v) + (assign(t,u), ...); + else + (assign(t,mv(u)), ...); + }); + }); + return l; + } +}; +template +constexpr void swap(tupl& l, decltype(l) r) + noexcept((std::is_nothrow_swappable_v && ...)) + requires (std::swappable && ...) +{ + map(l, [&r](T&...t) { + map(r, [&t...](T&...u) { + (std::ranges::swap(t, u), ...); + }); + }); +} +// tupl size N pack specializations +//#define TUPL_TIE_T tupl_tie_t +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0; + static consteval auto size() noexcept { return 0x0 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0))) { return f(((T&&)t).x0); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1; + static consteval auto size() noexcept { return 0x1 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1))) { return f(((T&&)t).x0,((T&&)t).x1); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2; + static consteval auto size() noexcept { return 0x2 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3; + static consteval auto size() noexcept { return 0x3 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4; + static consteval auto size() noexcept { return 0x4 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5; + static consteval auto size() noexcept { return 0x5 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6; + static consteval auto size() noexcept { return 0x6 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7; + static consteval auto size() noexcept { return 0x7 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8; + static consteval auto size() noexcept { return 0x8 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8;[[no_unique_address]] X9 x9; + static consteval auto size() noexcept { return 0x9 +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8;[[no_unique_address]] X9 x9;[[no_unique_address]] Xa xa; + static consteval auto size() noexcept { return 0xa +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8;[[no_unique_address]] X9 x9;[[no_unique_address]] Xa xa;[[no_unique_address]] Xb xb; + static consteval auto size() noexcept { return 0xb +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8;[[no_unique_address]] X9 x9;[[no_unique_address]] Xa xa;[[no_unique_address]] Xb xb;[[no_unique_address]] Xc xc; + static consteval auto size() noexcept { return 0xc +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8;[[no_unique_address]] X9 x9;[[no_unique_address]] Xa xa;[[no_unique_address]] Xb xb;[[no_unique_address]] Xc xc;[[no_unique_address]] Xd xd; + static consteval auto size() noexcept { return 0xd +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc,((T&&)t).xd))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc,((T&&)t).xd); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8;[[no_unique_address]] X9 x9;[[no_unique_address]] Xa xa;[[no_unique_address]] Xb xb;[[no_unique_address]] Xc xc;[[no_unique_address]] Xd xd;[[no_unique_address]] Xe xe; + static consteval auto size() noexcept { return 0xe +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc,((T&&)t).xd,((T&&)t).xe))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc,((T&&)t).xd,((T&&)t).xe); } +}; +template +struct tupl +{ +// using tie_t = TUPL_TIE_T const; + using tupl_t = tupl; + [[no_unique_address]] X0 x0;[[no_unique_address]] X1 x1;[[no_unique_address]] X2 x2;[[no_unique_address]] X3 x3;[[no_unique_address]] X4 x4;[[no_unique_address]] X5 x5;[[no_unique_address]] X6 x6;[[no_unique_address]] X7 x7;[[no_unique_address]] X8 x8;[[no_unique_address]] X9 x9;[[no_unique_address]] Xa xa;[[no_unique_address]] Xb xb;[[no_unique_address]] Xc xc;[[no_unique_address]] Xd xd;[[no_unique_address]] Xe xe;[[no_unique_address]] Xf xf; + static consteval auto size() noexcept { return 0xf +1; } + friend auto operator<=>(tupl const&,tupl const&) + requires tupl_types_all = default; + templateconstexpr auto& operator=(tupl<>) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = {};} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) + requires (tupl_val&&tupl_types_all) + {return assign_to{*this} = r;} + templateconstexpr auto& operator=(tupl_assign_fwd_t r) const + requires tupl_tie + {return assign_to{*this} = r;} + constexpr auto& operator=(std::same_as> auto const& r) const + {return assign_to{*this} = r;} + template T> friend constexpr decltype(auto) map(T&& t, auto f) noexcept(noexcept(f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc,((T&&)t).xd,((T&&)t).xe,((T&&)t).xf))) { return f(((T&&)t).x0,((T&&)t).x1,((T&&)t).x2,((T&&)t).x3,((T&&)t).x4,((T&&)t).x5,((T&&)t).x6,((T&&)t).x7,((T&&)t).x8,((T&&)t).x9,((T&&)t).xa,((T&&)t).xb,((T&&)t).xc,((T&&)t).xd,((T&&)t).xe,((T&&)t).xf); } +}; +template requires (! tupl_types_all + && tupl_types_all) +constexpr auto operator<=>(T const& l,T const& r) noexcept { + constexpr auto s = tupl_size; + constexpr compare_three_way cmp; + if constexpr(0x0 requires (! tupl_types_all + && tupl_types_all) +constexpr auto operator==(T const& l,T const& r) noexcept { + return l <=> r == 0; +} +template requires (! tupl_types_all + && ! tupl_types_all + && tupl_types_all) +constexpr bool operator==(T const& l,T const& r) noexcept { + constexpr auto s = tupl_size; + if constexpr(0x0(t) +template constexpr auto&& get(tuplish auto&& t) noexcept + requires (I < t.size()) +{ + using T = decltype(t); + if constexpr(I==0x0)return((T)t).x0;else if constexpr(I==0x1)return((T)t).x1;else if constexpr(I==0x2)return((T)t).x2;else if constexpr(I==0x3)return((T)t).x3;else if constexpr(I==0x4)return((T)t).x4;else if constexpr(I==0x5)return((T)t).x5;else if constexpr(I==0x6)return((T)t).x6;else if constexpr(I==0x7)return((T)t).x7;else if constexpr(I==0x8)return((T)t).x8;else if constexpr(I==0x9)return((T)t).x9;else if constexpr(I==0xa)return((T)t).xa;else if constexpr(I==0xb)return((T)t).xb;else if constexpr(I==0xc)return((T)t).xc;else if constexpr(I==0xd)return((T)t).xd;else if constexpr(I==0xe)return((T)t).xe;else if constexpr(I==0xf)return((T)t).xf; + UNREACHABLE(); +} +// Index of first element of type X +template requires (std::same_as || ...) +inline constexpr int indexof = []() consteval { + using std::same_as; + using T = tupl; + if constexpr(same_as)return 0x0;else if constexpr(same_as)return 0x1;else if constexpr(same_as)return 0x2;else if constexpr(same_as)return 0x3;else if constexpr(same_as)return 0x4;else if constexpr(same_as)return 0x5;else if constexpr(same_as)return 0x6;else if constexpr(same_as)return 0x7;else if constexpr(same_as)return 0x8;else if constexpr(same_as)return 0x9;else if constexpr(same_as)return 0xa;else if constexpr(same_as)return 0xb;else if constexpr(same_as)return 0xc;else if constexpr(same_as)return 0xd;else if constexpr(same_as)return 0xe;else if constexpr(same_as)return 0xf; + UNREACHABLE(); +}(); +// +template +inline constexpr int tupl_indexof = not defined(tupl_indexof); +template +inline constexpr int tupl_indexof> = indexof; +template +constexpr auto tie(T&...t) noexcept + -> tupl const +{ + return { t... }; +}; +template +constexpr auto getie(tuplish auto&& t) noexcept + -> tupl((decltype(t))t))...> const + requires ((I < t.size()) && ...) + { return {get((decltype(t))t)...}; }; +template +constexpr auto dupl(tuplconst& a) + -> tupl(a))...> + { return {get(a)...}; }; +template +constexpr auto dupl(tuplconst& a) -> tupl + { return {get(a)...}; }; +} // CLOSE namespace NAMESPACE_ID diff --git a/whats_tupl_docs.svg b/whats_tupl_docs.svg deleted file mode 100644 index 078c8c7..0000000 --- a/whats_tupl_docs.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -