Add the ability to build as a header only library

This commit is contained in:
sha512sum 2024-08-28 08:18:54 +00:00
parent fd757260c5
commit 4548b03c67
31 changed files with 402 additions and 184 deletions

4
.gitignore vendored
View file

@ -20,5 +20,5 @@ utemplConfigVersion.cmake
utempl_tests utempl_tests
utempl_tests\[1\]_include.cmake utempl_tests\[1\]_include.cmake
utempl_tests\[1\]_tests.cmake utempl_tests\[1\]_tests.cmake
libutempl_shared.so libutempl.a
libutempl_static.so _headers

View file

@ -12,10 +12,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_MODULE_STD 1) set(CMAKE_CXX_MODULE_STD 1)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(FMT_MODULE ON)
set(BOOST_INCLUDE_LIBRARIES "pfr") set(BOOST_INCLUDE_LIBRARIES "pfr")
option(CPM_USE_LOCAL_PACKAGES "Use local packages" ON) option(CPM_USE_LOCAL_PACKAGES "Use local packages" ON)
option(UTEMPL_MODULE OFF)
if(UTEMPL_MODULE)
add_compile_definitions(UTEMPL_EXPORT=export)
elseif()
add_compile_definitions(UTEMPL_EXPORT="")
endif()
file(GLOB_RECURSE SOURCES "src/*.cpp") file(GLOB_RECURSE SOURCES "src/*.cpp")
set_target_properties(__cmake_cxx23 PROPERTIES CXX_EXTENSIONS OFF) set_target_properties(__cmake_cxx23 PROPERTIES CXX_EXTENSIONS OFF)
@ -38,6 +45,8 @@ CPMAddPackage(
OPTIONS "BOOST_SKIP_INSTALL_RULES OFF" OPTIONS "BOOST_SKIP_INSTALL_RULES OFF"
) )
if(UTEMPL_MODULE)
set(TMP ${CPM_USE_LOCAL_PACKAGES}) set(TMP ${CPM_USE_LOCAL_PACKAGES})
set(CPM_USE_LOCAL_PACKAGES OFF) set(CPM_USE_LOCAL_PACKAGES OFF)
@ -45,29 +54,93 @@ CPMAddPackage(
NAME fmt NAME fmt
URL URL
"https://github.com/linuxnyasha/fmt_import/archive/refs/heads/linuxnyasha-patch-1.zip" "https://github.com/linuxnyasha/fmt_import/archive/refs/heads/linuxnyasha-patch-1.zip"
EXCLUDE_FROM_ALL ON
OPTIONS "FMT_MODULE ON"
# Fixes for fmt module and constexpr fmt::formatted_size # Fixes for fmt module and constexpr fmt::formatted_size
) )
set(CPM_USE_LOCAL_PACKAGES ${TMP}) set(CPM_USE_LOCAL_PACKAGES ${TMP})
else()
CPMAddPackage("gh:fmtlib/fmt#11.0.2")
endif()
cmake_policy(SET CMP0079 NEW) cmake_policy(SET CMP0079 NEW)
include(GNUInstallDirs) include(GNUInstallDirs)
file(MAKE_DIRECTORY "_headers")
file(MAKE_DIRECTORY "_headers/utempl")
file(MAKE_DIRECTORY "_headers/utempl/loopholes")
if(UTEMPL_MODULE)
add_library(utempl STATIC)
target_compile_definitions(utempl PUBLIC UTEMPL_MODULE)
target_compile_options(utempl PUBLIC "-Wno-pragma-once-outside-header")
target_sources(utempl PUBLIC FILE_SET utemplModules TYPE CXX_MODULES
FILES ${SOURCES})
file(GLOB_RECURSE HEADER_SOURCES "src/*.hpp")
set(EXISTING_HEADERS)
foreach(HPP_FILE ${HEADER_SOURCES})
get_filename_component(FILE_NAME ${HPP_FILE} NAME_WE)
set(HEADER_FILE "_headers/utempl/${FILE_NAME}.hpp")
file(READ ${HPP_FILE} FILE_CONTENT)
file(WRITE ${HEADER_FILE} "${FILE_CONTENT}")
list(APPEND EXISTING_HEADERS "${HEADER_FILE}")
endforeach()
file(GLOB HEADER_FILES "_headers/*.hpp")
foreach(HEADER_FILE ${HEADER_FILES})
if(NOT HEADER_FILE IN_LIST EXISTING_HEADERS)
file(REMOVE ${HEADER_FILE})
endif()
endforeach()
if(TARGET Boost::pfr)
target_link_libraries(utempl PUBLIC fmt::fmt
Boost::pfr)
else()
find_package(Boost 1.85.0 REQUIRED)
target_link_libraries(utempl PUBLIC fmt::fmt
${Boost_LIBRARIES})
endif()
else()
add_library(utempl INTERFACE)
file(GLOB_RECURSE HEADER_SOURCES "src/*.hpp")
set(EXISTING_HEADERS)
foreach(CPP_FILE ${SOURCES} ${HEADER_SOURCES})
get_filename_component(FILE_NAME ${CPP_FILE} NAME_WE)
set(HEADER_FILE "_headers/utempl/${FILE_NAME}.hpp")
file(READ ${CPP_FILE} FILE_CONTENT)
file(WRITE ${HEADER_FILE} "${FILE_CONTENT}")
list(APPEND EXISTING_HEADERS "${HEADER_FILE}")
endforeach()
file(GLOB HEADER_FILES "_headers/*.hpp")
foreach(HEADER_FILE ${HEADER_FILES})
if(NOT HEADER_FILE IN_LIST EXISTING_HEADERS)
file(REMOVE ${HEADER_FILE})
endif()
endforeach()
if(TARGET Boost::pfr)
target_link_libraries(utempl INTERFACE fmt::fmt
Boost::pfr)
else()
find_package(Boost 1.85.0 REQUIRED)
target_link_libraries(utempl INTERFACE fmt::fmt
${Boost_LIBRARIES})
endif()
endif()
add_library(utempl)
add_library(utempl::utempl ALIAS utempl) add_library(utempl::utempl ALIAS utempl)
target_compile_features(utempl INTERFACE cxx_std_23) target_compile_features(utempl INTERFACE cxx_std_23)
target_include_directories(utempl INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> target_include_directories(utempl INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/_headers>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_sources(utempl PUBLIC FILE_SET utemplModules TYPE CXX_MODULES
FILES ${SOURCES})
@ -80,16 +153,6 @@ install(TARGETS utempl
) )
if(TARGET Boost::pfr)
target_link_libraries(utempl PUBLIC fmt::fmt
Boost::pfr)
else()
find_package(Boost 1.85.0 REQUIRED)
target_link_libraries(utempl PUBLIC fmt::fmt
${Boost_LIBRARIES})
endif()
@ -113,7 +176,7 @@ install(FILES "${PROJECT_BINARY_DIR}/utemplConfig.cmake"
"${PROJECT_BINARY_DIR}/utemplConfigVersion.cmake" "${PROJECT_BINARY_DIR}/utemplConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/utempl/cmake) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/utempl/cmake)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/utempl DESTINATION include) install(DIRECTORY ${PROJECT_SOURCE_DIR}/headers/utempl DESTINATION include)
@ -122,8 +185,7 @@ if(ENABLE_TESTS)
enable_testing() enable_testing()
file(GLOB SOURCES tests/* tests/*/* tests/*/*/*) file(GLOB SOURCES tests/* tests/*/* tests/*/*/*)
add_executable(utempl_tests) add_executable(utempl_tests)
target_sources(utempl_tests PUBLIC FILE_SET utempl_tests TYPE CXX_MODULES target_sources(utempl_tests PUBLIC ${SOURCES})
FILES ${SOURCES})
target_link_libraries(utempl_tests GTest::gtest_main utempl::utempl) target_link_libraries(utempl_tests GTest::gtest_main utempl::utempl)
set_property(TARGET utempl_tests PROPERTY CXX_STANDARD 23) set_property(TARGET utempl_tests PROPERTY CXX_STANDARD 23)
include(GoogleTest) include(GoogleTest)

View file

@ -1,6 +1,6 @@
import std; #include <utempl/utempl.hpp>
import utempl;
#include <utempl/macro.hpp> #include <utempl/macro.hpp>
import std;
template <typename T> template <typename T>
struct AttributeData { struct AttributeData {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,5 +1,4 @@
import fmt; #include <utempl/utempl.hpp>
import utempl;
import std; import std;
struct SomeInterfaceImpl { struct SomeInterfaceImpl {
@ -13,7 +12,7 @@ struct SomeStruct {
}; };
inline auto Func(SomeInterface arg) { inline auto Func(SomeInterface arg) {
fmt::print("{} {}\n", arg.a, arg.b); std::println("{} {}\n", arg.a, arg.b);
}; };
auto main() -> int { auto main() -> int {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
struct Container { struct Container {
float data{}; float data{};

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,4 +1,4 @@
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,5 +1,5 @@
#include <cassert> #include <cassert>
import utempl; #include <utempl/utempl.hpp>
import std; import std;
auto main() -> int { auto main() -> int {

View file

@ -1,54 +1,66 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.attributes; export module utempl.attributes;
export import utempl.meta_info; export import utempl.meta_info;
export import utempl.tuple; export import utempl.tuple;
export import utempl.loopholes.counter; export import utempl.loopholes.counter;
import utempl.utils; import utempl.utils;
import utempl.type_list; import utempl.type_list;
#else
#include <utempl/loopholes/counter.hpp>
#include <utempl/meta_info.hpp>
#include <utempl/tuple.hpp>
#include <utempl/type_list.hpp>
#include <utempl/utils.hpp>
#endif
namespace utempl { namespace utempl {
namespace impl { namespace impl {
export struct AttributesTag {}; UTEMPL_EXPORT struct AttributesTag {};
export template <typename T> UTEMPL_EXPORT template <typename T>
struct AttributesCounterTag {}; struct AttributesCounterTag {};
} // namespace impl } // namespace impl
export template <typename T, typename..., auto f = [] {}, auto = AddTypeToTag<impl::AttributesTag, T, decltype(f)>()> UTEMPL_EXPORT template <typename T, typename..., auto f = [] {}, auto = AddTypeToTag<impl::AttributesTag, T, decltype(f)>()>
consteval auto OpenStruct() -> bool { consteval auto OpenStruct() -> bool {
return true; return true;
}; };
export template <typename..., UTEMPL_EXPORT template <typename...,
auto f = [] {}, auto f = [] {},
auto I = loopholes::CountValue<impl::AttributesTag, decltype(f)>(), auto I = loopholes::CountValue<impl::AttributesTag, decltype(f)>(),
auto II = (I >= 2) ? I - 2 : I - 1, auto II = (I >= 2) ? I - 2 : I - 1,
typename T = decltype(Magic(loopholes::Getter<MetaInfoKey<II, impl::AttributesTag>{}>{}))::Type, typename T = decltype(Magic(loopholes::Getter<MetaInfoKey<II, impl::AttributesTag>{}>{}))::Type,
auto = AddTypeToTag<impl::AttributesTag, T, decltype(f)>()> auto = AddTypeToTag<impl::AttributesTag, T, decltype(f)>()>
consteval auto CloseStruct() -> bool { consteval auto CloseStruct() -> bool {
return true; return true;
}; };
export struct NoInfo { UTEMPL_EXPORT struct NoInfo {
consteval auto operator==(const NoInfo&) const -> bool = default; consteval auto operator==(const NoInfo&) const -> bool = default;
}; };
export template <typename T, UTEMPL_EXPORT template <typename T,
typename O = TypeList<>, typename O = TypeList<>,
auto f = [] {}, auto f = [] {},
typename Current = decltype(GetCurrentTagType<impl::AttributesTag, decltype(f)>())::Type, typename Current = decltype(GetCurrentTagType<impl::AttributesTag, decltype(f)>())::Type,
auto = AddTypeToTag<impl::AttributesCounterTag<Current>, O, decltype(f)>()> auto = AddTypeToTag<impl::AttributesCounterTag<Current>, O, decltype(f)>()>
using FieldAttribute = T; using FieldAttribute = T;
export template <typename T, auto f = [] {}, bool R = (loopholes::CountValue<impl::AttributesCounterTag<T>, decltype(f)>() > 0)> UTEMPL_EXPORT template <typename T, auto f = [] {}, bool R = (loopholes::CountValue<impl::AttributesCounterTag<T>, decltype(f)>() > 0)>
concept HasAttributes = R; concept HasAttributes = R;
export template <typename T> UTEMPL_EXPORT template <typename T>
concept HasMacroAttributes = requires { T::template GetAttribute<0>(); }; concept HasMacroAttributes = requires { T::template GetAttribute<0>(); };
export template <HasAttributes T> UTEMPL_EXPORT template <HasAttributes T>
consteval auto GetAttributes() consteval auto GetAttributes()
requires HasMacroAttributes<T> requires HasMacroAttributes<T>
{ {
@ -58,7 +70,7 @@ consteval auto GetAttributes()
} | kSeq<I>; } | kSeq<I>;
}; };
export template <typename T> UTEMPL_EXPORT template <typename T>
consteval auto GetAttributes() { consteval auto GetAttributes() {
constexpr auto I = loopholes::CountValue<impl::AttributesCounterTag<T>>(); constexpr auto I = loopholes::CountValue<impl::AttributesCounterTag<T>>();
return return

View file

@ -1,9 +1,16 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.string; export module utempl.string;
import std; import std;
// import fmt; #else
#include <algorithm>
#include <string>
#endif
export namespace utempl { UTEMPL_EXPORT_BEGIN
namespace utempl {
template <std::size_t Size> template <std::size_t Size>
struct ConstexprString { struct ConstexprString {
std::array<char, Size> data; std::array<char, Size> data;
@ -78,3 +85,5 @@ constexpr auto CreateStringWith(char c) {
template <std::size_t Size> template <std::size_t Size>
ConstexprString(const char (&data)[Size]) -> ConstexprString<Size>; // NOLINT ConstexprString(const char (&data)[Size]) -> ConstexprString<Size>; // NOLINT
} // namespace utempl } // namespace utempl
UTEMPL_EXPORT_END

View file

@ -1,9 +1,21 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
module; module;
#include <boost/pfr.hpp> #include <boost/pfr.hpp>
export module utempl.go_interface; export module utempl.go_interface;
import std; import std;
import utempl.string; import utempl.string;
#else
#include <boost/pfr.hpp>
#include <utempl/constexpr_string.hpp>
#endif
namespace utempl { namespace utempl {
template <ConstexprString name, typename T> template <ConstexprString name, typename T>
@ -40,7 +52,7 @@ constexpr auto Transform(Transformer&& transformer, From&& from) {
}(std::make_index_sequence<boost::pfr::tuple_size_v<To>>()); }(std::make_index_sequence<boost::pfr::tuple_size_v<To>>());
}; };
export struct DefaultFieldTransformer { UTEMPL_EXPORT struct DefaultFieldTransformer {
constexpr auto operator()(auto&& arg) -> auto&& { constexpr auto operator()(auto&& arg) -> auto&& {
return arg; return arg;
}; };
@ -53,7 +65,7 @@ export struct DefaultFieldTransformer {
}; };
}; };
export template <typename Value, typename Transformer = DefaultFieldTransformer> UTEMPL_EXPORT template <typename Value, typename Transformer = DefaultFieldTransformer>
struct GoInterface : Value { struct GoInterface : Value {
constexpr GoInterface(Value&& value) : Value(std::move(value)) {}; // NOLINT constexpr GoInterface(Value&& value) : Value(std::move(value)) {}; // NOLINT
constexpr GoInterface(const Value& value) : Value(value) {}; // NOLINT constexpr GoInterface(const Value& value) : Value(value) {}; // NOLINT

View file

@ -1,20 +1,32 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.loopholes.core; export module utempl.loopholes.core;
import std; import std;
#else
#include <type_traits>
#endif
namespace utempl::loopholes { namespace utempl::loopholes {
export { UTEMPL_EXPORT_BEGIN
template <auto I> template <auto I>
struct Getter { struct Getter {
friend constexpr auto Magic(Getter<I>); friend constexpr auto Magic(Getter<I>);
};
template <auto I, auto Value = 0>
struct Injector {
friend constexpr auto Magic(Getter<I>) {
return Value;
}; };
template <auto I, auto Value = 0> };
struct Injector { UTEMPL_EXPORT_END
friend constexpr auto Magic(Getter<I>) {
return Value;
};
};
}
template <auto, typename = void, typename... Ts> template <auto, typename = void, typename... Ts>
struct InjectedImpl { struct InjectedImpl {
static constexpr bool value = false; static constexpr bool value = false;
@ -24,7 +36,7 @@ struct InjectedImpl<V, std::void_t<decltype(Magic(Getter<V>{}))>, Ts...> {
static constexpr bool value = true; static constexpr bool value = true;
}; };
export template <auto I, typename... Ts> UTEMPL_EXPORT template <auto I, typename... Ts>
concept Injected = InjectedImpl<I, void, Ts...>::value; concept Injected = InjectedImpl<I, void, Ts...>::value;
} // namespace utempl::loopholes } // namespace utempl::loopholes

View file

@ -1,7 +1,21 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.loopholes.counter; export module utempl.loopholes.counter;
export import utempl.loopholes.core; export import utempl.loopholes.core;
import std; import std;
#else
#include <utempl/loopholes/core.hpp>
#include <utility>
#endif
namespace utempl::loopholes { namespace utempl::loopholes {
template <typename Tag, std::size_t Value> template <typename Tag, std::size_t Value>

View file

@ -1,3 +1,11 @@
#pragma once
#ifdef UTEMPL_MODULE
export module utempl.loopholes; export module utempl.loopholes;
export import utempl.loopholes.core; export import utempl.loopholes.core;
export import utempl.loopholes.counter; export import utempl.loopholes.counter;
#else
#include <utempl/loopholes/core.hpp>
#include <utempl/loopholes/counter.hpp>
#endif

View file

@ -1,16 +1,23 @@
#pragma once
#ifdef UTEMPL_MODULE
export module utempl.meta_info; export module utempl.meta_info;
import utempl.loopholes; import utempl.loopholes;
import utempl.type_list; import utempl.type_list;
import std; import std;
#else
#include <utempl/loopholes/counter.hpp>
#include <utempl/module.hpp>
#include <utempl/type_list.hpp>
#endif
namespace utempl { namespace utempl {
export struct Types {}; UTEMPL_EXPORT struct Types {};
export template <std::size_t Id, typename Tag> UTEMPL_EXPORT template <std::size_t Id, typename Tag>
struct MetaInfoKey {}; struct MetaInfoKey {};
export template <typename T, typename Tag = Types> UTEMPL_EXPORT template <typename T, typename Tag = Types>
struct MetaInfo { struct MetaInfo {
static constexpr std::size_t kTypeId = loopholes::Counter<Tag, T>(); static constexpr std::size_t kTypeId = loopholes::Counter<Tag, T>();
using Type = T; using Type = T;
@ -19,23 +26,23 @@ struct MetaInfo {
static constexpr auto _ = loopholes::Injector<MetaInfoKey<kTypeId, Tag>{}, TypeList<T>{}>{}; static constexpr auto _ = loopholes::Injector<MetaInfoKey<kTypeId, Tag>{}, TypeList<T>{}>{};
}; };
export template <typename T, typename Tag = Types> UTEMPL_EXPORT template <typename T, typename Tag = Types>
inline constexpr std::size_t kTypeId = MetaInfo<T, Tag>::kTypeId; inline constexpr std::size_t kTypeId = MetaInfo<T, Tag>::kTypeId;
export template <typename Tag, UTEMPL_EXPORT template <typename Tag,
typename T, typename T,
typename... Ts, typename... Ts,
typename... TTs, typename... TTs,
std::size_t Id = loopholes::Counter<Tag, T, Ts..., TTs...>(), std::size_t Id = loopholes::Counter<Tag, T, Ts..., TTs...>(),
auto = loopholes::Injector<MetaInfoKey<Id, Tag>{}, TypeList<T>{}>{}> auto = loopholes::Injector<MetaInfoKey<Id, Tag>{}, TypeList<T>{}>{}>
consteval auto AddTypeToTag(TTs&&...) -> std::size_t { consteval auto AddTypeToTag(TTs&&...) -> std::size_t {
return Id; return Id;
}; };
export template <std::size_t Id, typename Tag = Types> UTEMPL_EXPORT template <std::size_t Id, typename Tag = Types>
using GetMetaInfo = MetaInfo<typename decltype(Magic(loopholes::Getter<MetaInfoKey<Id, Tag>{}>{}))::Type>; using GetMetaInfo = MetaInfo<typename decltype(Magic(loopholes::Getter<MetaInfoKey<Id, Tag>{}>{}))::Type>;
export template <std::size_t Id, typename Tag = Types> UTEMPL_EXPORT template <std::size_t Id, typename Tag = Types>
using GetType = GetMetaInfo<Id, Tag>::Type; using GetType = GetMetaInfo<Id, Tag>::Type;
template <typename Tag, std::size_t I = 0, typename... Ts, typename G> template <typename Tag, std::size_t I = 0, typename... Ts, typename G>
@ -55,12 +62,12 @@ static consteval auto GetTypeListForTag(G g)
}; };
}; };
export template <typename Tag = Types, typename... Ts> UTEMPL_EXPORT template <typename Tag = Types, typename... Ts>
consteval auto GetTypeListForTag() { consteval auto GetTypeListForTag() {
return GetTypeListForTag<Tag>(TypeList<Ts...>{}); return GetTypeListForTag<Tag>(TypeList<Ts...>{});
}; };
export template <typename Tag, typename... Ts, auto I = utempl::loopholes::CountValue<Tag, Ts...>() - 1> UTEMPL_EXPORT template <typename Tag, typename... Ts, auto I = utempl::loopholes::CountValue<Tag, Ts...>() - 1>
consteval auto GetCurrentTagType() { consteval auto GetCurrentTagType() {
return Magic(utempl::loopholes::Getter<MetaInfoKey<I, Tag>{}>()); return Magic(utempl::loopholes::Getter<MetaInfoKey<I, Tag>{}>());
}; };

View file

@ -1,9 +1,18 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.optional; export module utempl.optional;
import std; import std;
#else
#include <optional>
#endif
namespace utempl { namespace utempl {
export template <typename T> UTEMPL_EXPORT template <typename T>
struct Optional { // NOLINT struct Optional { // NOLINT
bool flag = false; bool flag = false;
union { union {

View file

@ -1,8 +1,16 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.overloaded; export module utempl.overloaded;
import std; import std;
#else
#include <type_traits>
#endif
namespace utempl { namespace utempl {
export template <typename... Fs> UTEMPL_EXPORT template <typename... Fs>
constexpr auto Overloaded(Fs&&... fs) { constexpr auto Overloaded(Fs&&... fs) {
struct Overloaded : public std::remove_cvref_t<Fs>... { struct Overloaded : public std::remove_cvref_t<Fs>... {
using Fs::operator()...; using Fs::operator()...;

View file

@ -1,12 +1,21 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.tuple; export module utempl.tuple;
import utempl.type_list; import utempl.type_list;
import utempl.overloaded; import utempl.overloaded;
import std; import std;
#else
#include <utempl/type_list.hpp>
#include <utility>
#endif
namespace utempl { namespace utempl {
export template <auto Value> UTEMPL_EXPORT template <auto Value>
struct Wrapper { struct Wrapper {
static constexpr auto kValue = Value; static constexpr auto kValue = Value;
static constexpr auto value = Value; static constexpr auto value = Value;
@ -35,10 +44,10 @@ struct TupleHelper<std::index_sequence<Is...>, Ts...> : public TupleLeaf<Is, Ts>
constexpr auto operator==(const TupleHelper&) const -> bool = default; constexpr auto operator==(const TupleHelper&) const -> bool = default;
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
struct Tuple; struct Tuple;
export template <std::size_t I, typename... Ts> UTEMPL_EXPORT template <std::size_t I, typename... Ts>
constexpr auto Get(Tuple<Ts...>& tuple) -> auto& constexpr auto Get(Tuple<Ts...>& tuple) -> auto&
requires(I < sizeof...(Ts)) requires(I < sizeof...(Ts))
{ {
@ -46,7 +55,7 @@ constexpr auto Get(Tuple<Ts...>& tuple) -> auto&
return static_cast<TupleLeaf<I, Type>&>(tuple).value; return static_cast<TupleLeaf<I, Type>&>(tuple).value;
}; };
export template <std::size_t I, typename... Ts> UTEMPL_EXPORT template <std::size_t I, typename... Ts>
constexpr auto Get(const Tuple<Ts...>& tuple) -> const auto& constexpr auto Get(const Tuple<Ts...>& tuple) -> const auto&
requires(I < sizeof...(Ts)) requires(I < sizeof...(Ts))
{ {
@ -54,7 +63,7 @@ constexpr auto Get(const Tuple<Ts...>& tuple) -> const auto&
return static_cast<const TupleLeaf<I, Type>&>(tuple).value; return static_cast<const TupleLeaf<I, Type>&>(tuple).value;
}; };
export template <std::size_t I, typename... Ts> UTEMPL_EXPORT template <std::size_t I, typename... Ts>
constexpr auto Get(Tuple<Ts...>&& tuple) -> decltype(auto) constexpr auto Get(Tuple<Ts...>&& tuple) -> decltype(auto)
requires(I < sizeof...(Ts)) requires(I < sizeof...(Ts))
{ {
@ -62,12 +71,12 @@ constexpr auto Get(Tuple<Ts...>&& tuple) -> decltype(auto)
return std::move(static_cast<TupleLeaf<I, Type>&&>(tuple).value); return std::move(static_cast<TupleLeaf<I, Type>&&>(tuple).value);
}; };
export template <std::size_t I, typename T> UTEMPL_EXPORT template <std::size_t I, typename T>
constexpr auto Get(T&& arg) -> decltype(get<I>(std::forward<T>(arg))) { constexpr auto Get(T&& arg) -> decltype(get<I>(std::forward<T>(arg))) {
return get<I>(std::forward<T>(arg)); return get<I>(std::forward<T>(arg));
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
struct Tuple : TupleHelper<std::index_sequence_for<Ts...>, Ts...> { struct Tuple : TupleHelper<std::index_sequence_for<Ts...>, Ts...> {
template <typename... TTs> template <typename... TTs>
constexpr Tuple(TTs&&... args) /* NOLINT */ : TupleHelper<std::index_sequence_for<Ts...>, Ts...>{{std::forward<TTs>(args)}...} {}; constexpr Tuple(TTs&&... args) /* NOLINT */ : TupleHelper<std::index_sequence_for<Ts...>, Ts...>{{std::forward<TTs>(args)}...} {};
@ -106,7 +115,7 @@ struct Tuple : TupleHelper<std::index_sequence_for<Ts...>, Ts...> {
}; };
}; };
export template <> UTEMPL_EXPORT template <>
struct Tuple<> { struct Tuple<> {
template <typename... Ts> template <typename... Ts>
constexpr auto operator+(const Tuple<Ts...>& other) const -> Tuple<Ts...> { constexpr auto operator+(const Tuple<Ts...>& other) const -> Tuple<Ts...> {
@ -116,10 +125,10 @@ struct Tuple<> {
return true; return true;
}; };
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
Tuple(Ts&&...) -> Tuple<std::decay_t<Ts>...>; Tuple(Ts&&...) -> Tuple<std::decay_t<Ts>...>;
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
consteval auto ListFromTuple(Tuple<Ts...>) -> TypeList<Ts...> { consteval auto ListFromTuple(Tuple<Ts...>) -> TypeList<Ts...> {
return {}; return {};
}; };

View file

@ -1,25 +1,36 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.type_list; export module utempl.type_list;
import std; import std;
import utempl.overloaded; import utempl.overloaded;
#else
#include <algorithm>
#include <utempl/overloaded.hpp>
#endif
namespace utempl { namespace utempl {
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
struct TypeList {}; struct TypeList {};
export template <typename T> UTEMPL_EXPORT template <typename T>
struct TypeList<T> { struct TypeList<T> {
using Type = T; using Type = T;
}; };
export template <typename T> UTEMPL_EXPORT template <typename T>
inline constexpr auto kType = TypeList<T>{}; inline constexpr auto kType = TypeList<T>{};
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
inline constexpr auto kTypeList = TypeList<Ts...>{}; inline constexpr auto kTypeList = TypeList<Ts...>{};
export template <typename T> UTEMPL_EXPORT template <typename T>
concept IsTypeList = Overloaded( concept IsTypeList = Overloaded(
[]<typename... Ts>(TypeList<TypeList<Ts...>>) { []<typename... Ts>(TypeList<TypeList<Ts...>>) {
return true; return true;
@ -37,45 +48,45 @@ struct Caster {};
template <std::size_t... Is, typename... Ts> template <std::size_t... Is, typename... Ts>
struct Caster<std::index_sequence<Is...>, Ts...> : IndexedType<Is, Ts>... {}; struct Caster<std::index_sequence<Is...>, Ts...> : IndexedType<Is, Ts>... {};
export template <typename... Ts, typename... TTs> UTEMPL_EXPORT template <typename... Ts, typename... TTs>
consteval auto operator==(const TypeList<Ts...>& first, const TypeList<TTs...>& second) -> bool { consteval auto operator==(const TypeList<Ts...>& first, const TypeList<TTs...>& second) -> bool {
return std::same_as<decltype(first), decltype(second)>; return std::same_as<decltype(first), decltype(second)>;
}; };
export template <typename... Ts, typename... TTs> UTEMPL_EXPORT template <typename... Ts, typename... TTs>
consteval auto operator+(const TypeList<Ts...>&, const TypeList<TTs...>&) -> TypeList<Ts..., TTs...> { consteval auto operator+(const TypeList<Ts...>&, const TypeList<TTs...>&) -> TypeList<Ts..., TTs...> {
return {}; return {};
}; };
export template <std::size_t I, typename... Ts> UTEMPL_EXPORT template <std::size_t I, typename... Ts>
consteval auto Get(TypeList<Ts...>) -> decltype([]<typename T>(IndexedType<I, T>&&) -> T { consteval auto Get(TypeList<Ts...>) -> decltype([]<typename T>(IndexedType<I, T>&&) -> T {
}(Caster<std::index_sequence_for<Ts...>, Ts...>{})); }(Caster<std::index_sequence_for<Ts...>, Ts...>{}));
export template <typename T, typename... Ts> UTEMPL_EXPORT template <typename T, typename... Ts>
consteval auto Find(TypeList<Ts...>) -> std::size_t { consteval auto Find(TypeList<Ts...>) -> std::size_t {
std::array<bool, sizeof...(Ts)> arr{std::same_as<T, Ts>...}; std::array<bool, sizeof...(Ts)> arr{std::same_as<T, Ts>...};
return std::ranges::find(arr, true) - arr.begin(); return std::ranges::find(arr, true) - arr.begin();
}; };
export template <template <typename...> typename F, typename... Ts> UTEMPL_EXPORT template <template <typename...> typename F, typename... Ts>
consteval auto Find(TypeList<Ts...>) -> std::size_t { consteval auto Find(TypeList<Ts...>) -> std::size_t {
std::array<bool, sizeof...(Ts)> arr{F<Ts>::value...}; std::array<bool, sizeof...(Ts)> arr{F<Ts>::value...};
return std::ranges::find(arr, true) - arr.begin(); return std::ranges::find(arr, true) - arr.begin();
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
consteval auto Reverse(TypeList<Ts...> list) { consteval auto Reverse(TypeList<Ts...> list) {
return [&]<auto... Is>(std::index_sequence<Is...>) -> TypeList<decltype(Get<sizeof...(Ts) - Is - 1>(list))...> { return [&]<auto... Is>(std::index_sequence<Is...>) -> TypeList<decltype(Get<sizeof...(Ts) - Is - 1>(list))...> {
return {}; return {};
}(std::index_sequence_for<Ts...>()); }(std::index_sequence_for<Ts...>());
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
consteval auto Transform(TypeList<Ts...>, auto&& f) -> TypeList<decltype(f(TypeList<Ts>{}))...> { consteval auto Transform(TypeList<Ts...>, auto&& f) -> TypeList<decltype(f(TypeList<Ts>{}))...> {
return {}; return {};
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
consteval auto FilterTypeList(TypeList<Ts...>, auto&& f) { consteval auto FilterTypeList(TypeList<Ts...>, auto&& f) {
return ((kTypeList<> + return ((kTypeList<> +
[](auto&& list) { [](auto&& list) {
@ -88,12 +99,12 @@ consteval auto FilterTypeList(TypeList<Ts...>, auto&& f) {
...); ...);
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
consteval auto Size(TypeList<Ts...>) -> std::size_t { consteval auto Size(TypeList<Ts...>) -> std::size_t {
return sizeof...(Ts); return sizeof...(Ts);
}; };
export template <std::size_t N, std::size_t From = 0, typename... Ts> UTEMPL_EXPORT template <std::size_t N, std::size_t From = 0, typename... Ts>
consteval auto TakeFrom(TypeList<Ts...> list) consteval auto TakeFrom(TypeList<Ts...> list)
requires(N + From <= sizeof...(Ts)) requires(N + From <= sizeof...(Ts))
{ {
@ -102,12 +113,12 @@ consteval auto TakeFrom(TypeList<Ts...> list)
}(std::make_index_sequence<N>()); }(std::make_index_sequence<N>());
}; };
export template <typename T, std::size_t N, typename... Ts> UTEMPL_EXPORT template <typename T, std::size_t N, typename... Ts>
consteval auto PushTo(TypeList<Ts...> list) { consteval auto PushTo(TypeList<Ts...> list) {
return TakeFrom<N>(list) + kType<T> + TakeFrom<sizeof...(Ts) - N, N>(list); return TakeFrom<N>(list) + kType<T> + TakeFrom<sizeof...(Ts) - N, N>(list);
}; };
export template <std::size_t N, typename... Ts> UTEMPL_EXPORT template <std::size_t N, typename... Ts>
consteval auto Erase(TypeList<Ts...> list) { consteval auto Erase(TypeList<Ts...> list) {
return TakeFrom<N>(list) + TakeFrom<sizeof...(Ts) - N - 1, N + 1>(list); return TakeFrom<N>(list) + TakeFrom<sizeof...(Ts) - N - 1, N + 1>(list);
}; };

6
src/utempl.hpp Normal file
View file

@ -0,0 +1,6 @@
#pragma once
#ifdef UTEMPL_MODULE
import utempl;
#else
#include <utempl/utempl_module.hpp>
#endif

29
src/utempl_module.cpp Normal file
View file

@ -0,0 +1,29 @@
#pragma once
#ifdef UTEMPL_MODULE
export module utempl;
export import utempl.type_list;
export import utempl.tuple;
export import utempl.string;
export import utempl.loopholes;
export import utempl.attributes;
export import utempl.meta_info;
export import utempl.overloaded;
export import utempl.utils;
export import utempl.go_interface;
export import utempl.optional;
#else
#include <utempl/attributes.hpp>
#include <utempl/constexpr_string.hpp>
#include <utempl/go_interface.hpp>
#include <utempl/loopholes/counter.hpp>
#include <utempl/macro.hpp>
#include <utempl/meta_info.hpp>
#include <utempl/optional.hpp>
#include <utempl/overloaded.hpp>
#include <utempl/tuple.hpp>
#include <utempl/type_list.hpp>
#endif

View file

@ -1,5 +1,9 @@
export module utempl.utils; #pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.utils;
import std; import std;
import fmt; import fmt;
import utempl.string; import utempl.string;
@ -7,21 +11,30 @@ import utempl.tuple;
import utempl.type_list; import utempl.type_list;
import utempl.overloaded; import utempl.overloaded;
#else
#include <utempl/constexpr_string.hpp>
#include <utempl/overloaded.hpp>
#include <utempl/tuple.hpp>
#include <utempl/type_list.hpp>
#endif
namespace utempl { namespace utempl {
template <typename T> template <typename T>
using ForwardType = decltype(std::forward<T>(std::declval<T>())); using ForwardType = decltype(std::forward<T>(std::declval<T>()));
export template <auto Value> UTEMPL_EXPORT template <auto Value>
constexpr Wrapper<Value> kWrapper; constexpr Wrapper<Value> kWrapper;
export template <typename T> UTEMPL_EXPORT template <typename T>
requires std::same_as<T, void> || requires { T{}; } requires std::same_as<T, void> || requires { T{}; }
constexpr auto kDefaultCreator = [] { constexpr auto kDefaultCreator = [] {
return T{}; return T{};
}; };
export template <> UTEMPL_EXPORT template <>
constexpr auto kDefaultCreator<void> = [] {}; constexpr auto kDefaultCreator<void> = [] {};
template <std::size_t N> template <std::size_t N>
@ -47,7 +60,7 @@ concept Function = []<typename R, typename... Ts>(TypeList<R(Ts...)>) {
static_assert(Function<decltype([]() {}), void()>); static_assert(Function<decltype([]() {}), void()>);
export template <std::size_t N> UTEMPL_EXPORT template <std::size_t N>
constexpr kSeqType<N> kSeq; constexpr kSeqType<N> kSeq;
template <ConstexprString string, typename T = std::size_t> template <ConstexprString string, typename T = std::size_t>
@ -62,14 +75,14 @@ consteval auto ParseNumber() -> T {
}; };
namespace literals { namespace literals {
export template <char... cs> UTEMPL_EXPORT template <char... cs>
consteval auto operator"" _c() { consteval auto operator"" _c() {
return Wrapper<ParseNumber<ConstexprString<sizeof...(cs)>({cs...})>()>{}; return Wrapper<ParseNumber<ConstexprString<sizeof...(cs)>({cs...})>()>{};
}; };
} // namespace literals } // namespace literals
export template <std::size_t I, typename... Ts> UTEMPL_EXPORT template <std::size_t I, typename... Ts>
constexpr auto Arg(Ts&&... args) -> decltype(auto) constexpr auto Arg(Ts&&... args) -> decltype(auto)
requires(I < sizeof...(Ts)) requires(I < sizeof...(Ts))
{ {
@ -80,52 +93,52 @@ constexpr auto Arg(Ts&&... args) -> decltype(auto)
}(std::make_index_sequence<I>()); }(std::make_index_sequence<I>());
}; };
export template <std::size_t Count> UTEMPL_EXPORT template <std::size_t Count>
constexpr auto Times(auto&& f) { constexpr auto Times(auto&& f) {
[&]<auto... Is>(std::index_sequence<Is...>) { [&]<auto... Is>(std::index_sequence<Is...>) {
(Arg<0>(f, Is)(), ...); (Arg<0>(f, Is)(), ...);
}(std::make_index_sequence<Count>()); }(std::make_index_sequence<Count>());
}; };
export template <typename T> UTEMPL_EXPORT template <typename T>
constexpr std::size_t kTupleSize = []() -> std::size_t { constexpr std::size_t kTupleSize = []() -> std::size_t {
static_assert(!sizeof(T), "Not Found"); static_assert(!sizeof(T), "Not Found");
return 0; return 0;
}(); }();
export template <typename T> UTEMPL_EXPORT template <typename T>
constexpr std::size_t kTupleSize<T&&> = kTupleSize<std::remove_reference_t<T>>; constexpr std::size_t kTupleSize<T&&> = kTupleSize<std::remove_reference_t<T>>;
export template <typename T> UTEMPL_EXPORT template <typename T>
constexpr std::size_t kTupleSize<T&> = kTupleSize<std::remove_reference_t<T>>; constexpr std::size_t kTupleSize<T&> = kTupleSize<std::remove_reference_t<T>>;
export template <typename T> UTEMPL_EXPORT template <typename T>
constexpr std::size_t kTupleSize<const T> = kTupleSize<std::remove_cv_t<T>>; constexpr std::size_t kTupleSize<const T> = kTupleSize<std::remove_cv_t<T>>;
export template <template <typename...> typename M, typename... Ts> UTEMPL_EXPORT template <template <typename...> typename M, typename... Ts>
constexpr std::size_t kTupleSize<M<Ts...>> = sizeof...(Ts); constexpr std::size_t kTupleSize<M<Ts...>> = sizeof...(Ts);
export template <template <typename, std::size_t> typename Array, typename T, std::size_t N> UTEMPL_EXPORT template <template <typename, std::size_t> typename Array, typename T, std::size_t N>
constexpr std::size_t kTupleSize<Array<T, N>> = N; constexpr std::size_t kTupleSize<Array<T, N>> = N;
export template <typename T> UTEMPL_EXPORT template <typename T>
struct TupleMaker {}; struct TupleMaker {};
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
struct TupleMaker<std::tuple<Ts...>> { struct TupleMaker<std::tuple<Ts...>> {
template <typename... Args> template <typename... Args>
static constexpr auto Make(Args&&... args) { static constexpr auto Make(Args&&... args) {
return std::tuple{std::forward<Args>(args)...}; return std::tuple{std::forward<Args>(args)...};
}; };
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
struct TupleMaker<Tuple<Ts...>> { struct TupleMaker<Tuple<Ts...>> {
template <typename... Args> template <typename... Args>
static constexpr auto Make(Args&&... args) { static constexpr auto Make(Args&&... args) {
return Tuple{std::forward<Args>(args)...}; return Tuple{std::forward<Args>(args)...};
}; };
}; };
export template <typename T, std::size_t N> UTEMPL_EXPORT template <typename T, std::size_t N>
struct TupleMaker<std::array<T, N>> { struct TupleMaker<std::array<T, N>> {
template <typename Arg, typename... Args> template <typename Arg, typename... Args>
static constexpr auto Make(Arg&& arg, Args&&... args) static constexpr auto Make(Arg&& arg, Args&&... args)
@ -138,10 +151,10 @@ struct TupleMaker<std::array<T, N>> {
}; };
}; };
export template <typename T> UTEMPL_EXPORT template <typename T>
struct TupleTieMaker {}; struct TupleTieMaker {};
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
struct TupleTieMaker<std::tuple<Ts...>> { struct TupleTieMaker<std::tuple<Ts...>> {
template <typename... Args> template <typename... Args>
static constexpr auto Make(Args&... args) -> std::tuple<Args...> { static constexpr auto Make(Args&... args) -> std::tuple<Args...> {
@ -149,7 +162,7 @@ struct TupleTieMaker<std::tuple<Ts...>> {
}; };
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
struct TupleTieMaker<Tuple<Ts...>> { struct TupleTieMaker<Tuple<Ts...>> {
template <typename... Args> template <typename... Args>
static constexpr auto Make(Args&... args) -> Tuple<Args...> { static constexpr auto Make(Args&... args) -> Tuple<Args...> {
@ -157,12 +170,12 @@ struct TupleTieMaker<Tuple<Ts...>> {
}; };
}; };
export template <typename T = Tuple<>, typename... Args> UTEMPL_EXPORT template <typename T = Tuple<>, typename... Args>
constexpr auto MakeTuple(Args&&... args) -> decltype(TupleMaker<std::remove_cvref_t<T>>::Make(std::forward<Args>(args)...)) { constexpr auto MakeTuple(Args&&... args) -> decltype(TupleMaker<std::remove_cvref_t<T>>::Make(std::forward<Args>(args)...)) {
return TupleMaker<std::remove_cvref_t<T>>::Make(std::forward<Args>(args)...); return TupleMaker<std::remove_cvref_t<T>>::Make(std::forward<Args>(args)...);
}; };
export template <typename T = Tuple<>, typename... Args> UTEMPL_EXPORT template <typename T = Tuple<>, typename... Args>
constexpr auto MakeTie(Args&... args) -> decltype(TupleTieMaker<std::remove_cvref_t<T>>::Make(args...)) { constexpr auto MakeTie(Args&... args) -> decltype(TupleTieMaker<std::remove_cvref_t<T>>::Make(args...)) {
return TupleTieMaker<std::remove_cvref_t<T>>::Make(args...); return TupleTieMaker<std::remove_cvref_t<T>>::Make(args...);
}; };
@ -210,17 +223,17 @@ struct IsSafeTuple<
static constexpr bool value = false; static constexpr bool value = false;
}; };
export template <typename T> UTEMPL_EXPORT template <typename T>
constexpr bool kForceEnableTuple = false; constexpr bool kForceEnableTuple = false;
export template <typename T, std::size_t N> UTEMPL_EXPORT template <typename T, std::size_t N>
constexpr bool kForceEnableTuple<std::array<T, N>> = true; constexpr bool kForceEnableTuple<std::array<T, N>> = true;
export template <typename T> UTEMPL_EXPORT template <typename T>
concept TupleLike = kForceEnableTuple<std::remove_cvref_t<T>> || concept TupleLike = kForceEnableTuple<std::remove_cvref_t<T>> ||
(requires { Get<0>(MakeTuple<T>(42)); } && IsSafeTuple<std::remove_cvref_t<T>>::value); // NOLINT (requires { Get<0>(MakeTuple<T>(42)); } && IsSafeTuple<std::remove_cvref_t<T>>::value); // NOLINT
export template <typename F, typename Tuple> UTEMPL_EXPORT template <typename F, typename Tuple>
concept TupleTransformer = requires(F f, Tuple&& tuple) { concept TupleTransformer = requires(F f, Tuple&& tuple) {
{ f(std::move(tuple)) }; { f(std::move(tuple)) };
}; };
@ -304,7 +317,7 @@ struct TupleMaker<LazyTuple<F>> {
}; };
}; };
export template <TupleLike Tuple, TupleTransformer<Tuple> FF> UTEMPL_EXPORT template <TupleLike Tuple, TupleTransformer<Tuple> FF>
constexpr auto operator|(Tuple&& tuple, FF&& f) { constexpr auto operator|(Tuple&& tuple, FF&& f) {
return LazyTuple{[tuple = std::forward<Tuple>(tuple), f = std::forward<FF>(f)]() -> decltype(auto) { return LazyTuple{[tuple = std::forward<Tuple>(tuple), f = std::forward<FF>(f)]() -> decltype(auto) {
return f(std::move(tuple)); return f(std::move(tuple));
@ -331,14 +344,14 @@ concept ForEachConcept = []<std::size_t... Is>(std::index_sequence<Is...>) {
return (std::invocable<F, decltype(Get<Is>(std::declval<Tuple>()))> && ...); return (std::invocable<F, decltype(Get<Is>(std::declval<Tuple>()))> && ...);
}(std::make_index_sequence<kTupleSize<Tuple>>()); }(std::make_index_sequence<kTupleSize<Tuple>>());
export template <TupleLike Tuple, UnpackConcept<Tuple> F> UTEMPL_EXPORT template <TupleLike Tuple, UnpackConcept<Tuple> F>
constexpr auto Unpack(Tuple&& tuple, F&& f) -> decltype(auto) { constexpr auto Unpack(Tuple&& tuple, F&& f) -> decltype(auto) {
return [&](auto... is) -> decltype(auto) { return [&](auto... is) -> decltype(auto) {
return f(Get<is>(std::forward<Tuple>(tuple))...); return f(Get<is>(std::forward<Tuple>(tuple))...);
} | kSeq<kTupleSize<Tuple>>; } | kSeq<kTupleSize<Tuple>>;
}; };
export template <typename F> UTEMPL_EXPORT template <typename F>
constexpr auto Unpack(F&& f) { constexpr auto Unpack(F&& f) {
return [f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple) -> decltype(auto) return [f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple) -> decltype(auto)
requires UnpackConcept<F, Tuple> requires UnpackConcept<F, Tuple>
@ -347,14 +360,14 @@ constexpr auto Unpack(F&& f) {
}; };
}; };
export template <TupleLike Tuple, TupleLike R = Tuple, TransformConcept<Tuple> F> UTEMPL_EXPORT template <TupleLike Tuple, TupleLike R = Tuple, TransformConcept<Tuple> F>
constexpr auto Transform(Tuple&& container, F&& f, TypeList<R> = {}) { constexpr auto Transform(Tuple&& container, F&& f, TypeList<R> = {}) {
return Unpack(std::forward<Tuple>(container), [&]<typename... Ts>(Ts&&... args) { return Unpack(std::forward<Tuple>(container), [&]<typename... Ts>(Ts&&... args) {
return MakeTuple<R>(f(std::forward<Ts>(args))...); return MakeTuple<R>(f(std::forward<Ts>(args))...);
}); });
}; };
export template <typename F, typename R = void> UTEMPL_EXPORT template <typename F, typename R = void>
constexpr auto Transform(F&& f, TypeList<R> result = {}) { constexpr auto Transform(F&& f, TypeList<R> result = {}) {
return [f = std::forward<F>(f), result]<TupleLike TTuple, typename RR = decltype([] { return [f = std::forward<F>(f), result]<TupleLike TTuple, typename RR = decltype([] {
if constexpr(std::same_as<R, void>) { if constexpr(std::same_as<R, void>) {
@ -369,17 +382,17 @@ constexpr auto Transform(F&& f, TypeList<R> result = {}) {
}; };
}; };
export template <TupleLike Tuple, TupleLike R = Tuple, TransformConcept<Tuple> F> UTEMPL_EXPORT template <TupleLike Tuple, TupleLike R = Tuple, TransformConcept<Tuple> F>
constexpr auto Map(Tuple&& tuple, F&& f, TypeList<R> result = {}) { constexpr auto Map(Tuple&& tuple, F&& f, TypeList<R> result = {}) {
return Transform(std::forward<Tuple>(tuple), std::forward<F>(f), result); return Transform(std::forward<Tuple>(tuple), std::forward<F>(f), result);
}; };
export template <typename F, typename R = void> UTEMPL_EXPORT template <typename F, typename R = void>
constexpr auto Map(F&& f, TypeList<R> result = {}) -> decltype(Transform(std::forward<F>(f), result)) { constexpr auto Map(F&& f, TypeList<R> result = {}) -> decltype(Transform(std::forward<F>(f), result)) {
return Transform(std::forward<F>(f), result); return Transform(std::forward<F>(f), result);
}; };
export template <auto Tuple, TupleLike To = decltype(Tuple)> UTEMPL_EXPORT template <auto Tuple, TupleLike To = decltype(Tuple)>
consteval auto PackConstexprWrapper() consteval auto PackConstexprWrapper()
requires TupleLike<decltype(Tuple)> requires TupleLike<decltype(Tuple)>
{ {
@ -388,14 +401,14 @@ consteval auto PackConstexprWrapper()
}(std::make_index_sequence<kTupleSize<decltype(Tuple)>>()); }(std::make_index_sequence<kTupleSize<decltype(Tuple)>>());
}; };
export template <TupleLike Tuple> UTEMPL_EXPORT template <TupleLike Tuple>
constexpr auto Reverse(Tuple&& tuple) { constexpr auto Reverse(Tuple&& tuple) {
return [&]<std::size_t... Is>(std::index_sequence<Is...>) { return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
return MakeTuple<Tuple>(Get<kTupleSize<Tuple> - Is - 1>(std::forward<Tuple>(tuple))...); return MakeTuple<Tuple>(Get<kTupleSize<Tuple> - Is - 1>(std::forward<Tuple>(tuple))...);
}(std::make_index_sequence<kTupleSize<Tuple>>()); }(std::make_index_sequence<kTupleSize<Tuple>>());
}; };
export consteval auto Reverse() { UTEMPL_EXPORT consteval auto Reverse() {
return []<TupleLike Tuple>(Tuple&& tuple) { return []<TupleLike Tuple>(Tuple&& tuple) {
return Reverse(std::forward<Tuple>(tuple)); return Reverse(std::forward<Tuple>(tuple));
}; };
@ -443,7 +456,7 @@ concept LeftFoldConcept = decltype(Unpack(std::declval<Tuple>(), []<typename...
return kWrapper<decltype((LeftFoldIsOk<F, T>{} | ... | LeftFoldIsOk<F, Ts>{}))::value>; return kWrapper<decltype((LeftFoldIsOk<F, T>{} | ... | LeftFoldIsOk<F, Ts>{}))::value>;
}))::kValue; }))::kValue;
export template <TupleLike Tuple, std::move_constructible T, LeftFoldConcept<T, Tuple> F = decltype(kDefaultCreator<void>)&> UTEMPL_EXPORT template <TupleLike Tuple, std::move_constructible T, LeftFoldConcept<T, Tuple> F = decltype(kDefaultCreator<void>)&>
constexpr auto LeftFold(Tuple&& tuple, T&& init, F&& f = kDefaultCreator<void>) -> decltype(auto) { constexpr auto LeftFold(Tuple&& tuple, T&& init, F&& f = kDefaultCreator<void>) -> decltype(auto) {
return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) -> decltype(auto) { return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) -> decltype(auto) {
return (LeftFoldHelper<ForwardType<T>, ForwardType<F>>{.data = std::forward<T>(init), .f = std::forward<F>(f)} | ... | return (LeftFoldHelper<ForwardType<T>, ForwardType<F>>{.data = std::forward<T>(init), .f = std::forward<F>(f)} | ... |
@ -452,12 +465,12 @@ constexpr auto LeftFold(Tuple&& tuple, T&& init, F&& f = kDefaultCreator<void>)
}); });
}; };
export template <TupleLike Tuple, std::move_constructible T, LeftFoldConcept<T, Tuple> F> UTEMPL_EXPORT template <TupleLike Tuple, std::move_constructible T, LeftFoldConcept<T, Tuple> F>
constexpr auto Reduce(Tuple&& tuple, T&& init, F&& f) -> decltype(auto) { constexpr auto Reduce(Tuple&& tuple, T&& init, F&& f) -> decltype(auto) {
return LeftFold(std::forward<Tuple>(tuple), std::forward<T>(init), std::forward<F>(f)); return LeftFold(std::forward<Tuple>(tuple), std::forward<T>(init), std::forward<F>(f));
}; };
export template <typename T, typename F> UTEMPL_EXPORT template <typename T, typename F>
constexpr auto Reduce(T&& init, F&& f) -> decltype(auto) { constexpr auto Reduce(T&& init, F&& f) -> decltype(auto) {
return [init = std::forward<T>(init), f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple) -> decltype(auto) return [init = std::forward<T>(init), f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple) -> decltype(auto)
requires LeftFoldConcept<F, T, Tuple> requires LeftFoldConcept<F, T, Tuple>
@ -466,14 +479,14 @@ constexpr auto Reduce(T&& init, F&& f) -> decltype(auto) {
}; };
}; };
export template <TupleLike Tuple, TupleLike Tuple2> UTEMPL_EXPORT template <TupleLike Tuple, TupleLike Tuple2>
constexpr auto TupleCat(Tuple&& tuple, Tuple2&& tuple2) { constexpr auto TupleCat(Tuple&& tuple, Tuple2&& tuple2) {
return [&]<auto... Is, auto... IIs>(std::index_sequence<Is...>, std::index_sequence<IIs...>) { return [&]<auto... Is, auto... IIs>(std::index_sequence<Is...>, std::index_sequence<IIs...>) {
return MakeTuple<Tuple>(Get<Is>(std::forward<Tuple>(tuple))..., Get<IIs>(std::forward<Tuple2>(tuple2))...); return MakeTuple<Tuple>(Get<Is>(std::forward<Tuple>(tuple))..., Get<IIs>(std::forward<Tuple2>(tuple2))...);
}(std::make_index_sequence<kTupleSize<Tuple>>(), std::make_index_sequence<kTupleSize<Tuple2>>()); }(std::make_index_sequence<kTupleSize<Tuple>>(), std::make_index_sequence<kTupleSize<Tuple2>>());
}; };
export template <TupleLike... Tuples> UTEMPL_EXPORT template <TupleLike... Tuples>
constexpr auto TupleCat(Tuples&&... tuples) constexpr auto TupleCat(Tuples&&... tuples)
requires(sizeof...(tuples) >= 1) requires(sizeof...(tuples) >= 1)
{ {
@ -484,12 +497,12 @@ constexpr auto TupleCat(Tuples&&... tuples)
}); });
}; };
export template <TupleLike... Tuples, typename F> UTEMPL_EXPORT template <TupleLike... Tuples, typename F>
constexpr auto Unpack(Tuples&&... tuples, F&& f) -> decltype(Unpack(TupleCat(std::forward<Tuples>(tuples)...), std::forward<F>(f))) { constexpr auto Unpack(Tuples&&... tuples, F&& f) -> decltype(Unpack(TupleCat(std::forward<Tuples>(tuples)...), std::forward<F>(f))) {
return Unpack(TupleCat(std::forward<Tuples>(tuples)...), std::forward<F>(f)); return Unpack(TupleCat(std::forward<Tuples>(tuples)...), std::forward<F>(f));
}; };
export template <typename... Ts> UTEMPL_EXPORT template <typename... Ts>
constexpr auto Tie(Ts&... args) -> Tuple<Ts&...> { constexpr auto Tie(Ts&... args) -> Tuple<Ts&...> {
return {args...}; return {args...};
}; };
@ -511,7 +524,7 @@ consteval auto PartialCallerF(TypeList<Ts...>) {
}; };
}; };
export template <TupleLike Tuple, std::move_constructible T> UTEMPL_EXPORT template <TupleLike Tuple, std::move_constructible T>
constexpr auto FirstOf(Tuple&& tuple, T&& init) constexpr auto FirstOf(Tuple&& tuple, T&& init)
requires kEveryElement<std::is_invocable, Tuple> requires kEveryElement<std::is_invocable, Tuple>
{ {
@ -523,7 +536,7 @@ constexpr auto FirstOf(Tuple&& tuple, T&& init)
}); });
}; };
export template <typename T> UTEMPL_EXPORT template <typename T>
constexpr auto FirstOf(T&& init) { constexpr auto FirstOf(T&& init) {
return [init = std::forward<T>(init)]<TupleLike Tuple>(Tuple&& tuple) { return [init = std::forward<T>(init)]<TupleLike Tuple>(Tuple&& tuple) {
return FirstOf(std::forward<Tuple>(tuple), std::move(init)); return FirstOf(std::forward<Tuple>(tuple), std::move(init));
@ -535,7 +548,7 @@ concept FilterConcept = decltype(Unpack(std::declval<Tuple>(), []<typename... Ts
return kWrapper<(Function<F, bool(Ts)> && ...)>; return kWrapper<(Function<F, bool(Ts)> && ...)>;
}))::kValue; }))::kValue;
export template <TupleLike Tuple, FilterConcept<Tuple> F> UTEMPL_EXPORT template <TupleLike Tuple, FilterConcept<Tuple> F>
constexpr auto Filter(Tuple&& tuple, F&& f) { constexpr auto Filter(Tuple&& tuple, F&& f) {
return LeftFold( return LeftFold(
std::forward<Tuple>(tuple), MakeTuple<Tuple>(), [&]<TupleLike Accumulator, typename T>(Accumulator&& accumulator, T&& add) { std::forward<Tuple>(tuple), MakeTuple<Tuple>(), [&]<TupleLike Accumulator, typename T>(Accumulator&& accumulator, T&& add) {
@ -547,7 +560,7 @@ constexpr auto Filter(Tuple&& tuple, F&& f) {
}); });
}; };
export template <typename F> UTEMPL_EXPORT template <typename F>
constexpr auto Filter(F&& f) { constexpr auto Filter(F&& f) {
return [f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple) return [f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple)
requires FilterConcept<F, Tuple> requires FilterConcept<F, Tuple>
@ -556,7 +569,7 @@ constexpr auto Filter(F&& f) {
}; };
}; };
export template <TupleLike Tuple, ForEachConcept<Tuple> F> UTEMPL_EXPORT template <TupleLike Tuple, ForEachConcept<Tuple> F>
constexpr auto ForEach(Tuple&& tuple, F&& f) { constexpr auto ForEach(Tuple&& tuple, F&& f) {
Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) { Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) {
(f(std::forward<Ts>(args)), ...); (f(std::forward<Ts>(args)), ...);
@ -577,12 +590,12 @@ struct Curryer {
return {.f = this->f, .data = this->data + Tuple{std::forward<T>(arg)}}; return {.f = this->f, .data = this->data + Tuple{std::forward<T>(arg)}};
}; };
}; };
export template <typename F> UTEMPL_EXPORT template <typename F>
constexpr auto Curry(F&& f) -> Curryer<std::remove_cvref_t<F>> { constexpr auto Curry(F&& f) -> Curryer<std::remove_cvref_t<F>> {
return {.f = std::forward<F>(f), .data = Tuple{}}; return {.f = std::forward<F>(f), .data = Tuple{}};
}; };
export template <TupleLike Tuple, typename T> UTEMPL_EXPORT template <TupleLike Tuple, typename T>
constexpr auto Find(Tuple&& tuple, T&& find) -> std::size_t { constexpr auto Find(Tuple&& tuple, T&& find) -> std::size_t {
return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) { return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) {
using Type = std::remove_cvref_t<T>; using Type = std::remove_cvref_t<T>;
@ -606,7 +619,7 @@ constexpr auto Find(Tuple&& tuple, T&& find) -> std::size_t {
}); });
}; };
export template <std::size_t N, TupleLike Tuple> UTEMPL_EXPORT template <std::size_t N, TupleLike Tuple>
constexpr auto Take(Tuple&& tuple) { constexpr auto Take(Tuple&& tuple) {
if constexpr(std::is_lvalue_reference_v<Tuple> && HasMakeTie<Tuple>) { if constexpr(std::is_lvalue_reference_v<Tuple> && HasMakeTie<Tuple>) {
return [&]<std::size_t... Is>(std::index_sequence<Is...>) { return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
@ -619,21 +632,21 @@ constexpr auto Take(Tuple&& tuple) {
}; };
}; };
export template <std::size_t N> UTEMPL_EXPORT template <std::size_t N>
consteval auto Take() { consteval auto Take() {
return [&]<TupleLike Tuple>(Tuple&& tuple) { return [&]<TupleLike Tuple>(Tuple&& tuple) {
return Take<N>(std::forward<Tuple>(tuple)); return Take<N>(std::forward<Tuple>(tuple));
}; };
}; };
export template <TupleLike Tuple, std::move_constructible T> UTEMPL_EXPORT template <TupleLike Tuple, std::move_constructible T>
constexpr auto operator<<(Tuple&& tuple, T&& t) { constexpr auto operator<<(Tuple&& tuple, T&& t) {
return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) { return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) {
return MakeTuple<Tuple>(std::forward<Ts>(args)..., std::forward<T>(t)); return MakeTuple<Tuple>(std::forward<Ts>(args)..., std::forward<T>(t));
}); });
}; };
export template <std::size_t N, TupleLike Tuple = Tuple<>, typename T> UTEMPL_EXPORT template <std::size_t N, TupleLike Tuple = Tuple<>, typename T>
constexpr auto Generate(T&& value) constexpr auto Generate(T&& value)
requires(std::copyable<T> || N == 1 && std::move_constructible<T>) requires(std::copyable<T> || N == 1 && std::move_constructible<T>)
{ {
@ -646,7 +659,7 @@ constexpr auto Generate(T&& value)
}; };
}; };
export template <TupleLike Tuple> UTEMPL_EXPORT template <TupleLike Tuple>
constexpr auto Enumerate(Tuple&& tuple) { constexpr auto Enumerate(Tuple&& tuple) {
return Unpack(std::forward<Tuple>(tuple), [](auto&&... vs) { return Unpack(std::forward<Tuple>(tuple), [](auto&&... vs) {
return [&](auto... is) { return [&](auto... is) {
@ -665,12 +678,12 @@ concept CallableSwitchConcept = std::same_as<R, void> || decltype(Unpack(std::de
return kWrapper<(Function<F, std::optional<R>(Ts)> && ...)>; return kWrapper<(Function<F, std::optional<R>(Ts)> && ...)>;
}))::kValue; }))::kValue;
export template <typename R = void, UTEMPL_EXPORT template <typename R = void,
TupleLike KeysTuple, TupleLike KeysTuple,
TupleLike ValuesTuple, TupleLike ValuesTuple,
ComparableSwitchConcept<KeysTuple> Key, ComparableSwitchConcept<KeysTuple> Key,
CallableSwitchConcept<ValuesTuple, R> F, CallableSwitchConcept<ValuesTuple, R> F,
Function<R()> Default = std::add_lvalue_reference_t<decltype(kDefaultCreator<R>)>> Function<R()> Default = std::add_lvalue_reference_t<decltype(kDefaultCreator<R>)>>
constexpr auto Switch(KeysTuple&& keysTuple, ValuesTuple&& valuesTuple, Key&& key, F&& f, Default&& def = kDefaultCreator<R>) -> R constexpr auto Switch(KeysTuple&& keysTuple, ValuesTuple&& valuesTuple, Key&& key, F&& f, Default&& def = kDefaultCreator<R>) -> R
requires(std::move_constructible<R> || std::same_as<R, void>) && (kTupleSize<KeysTuple> == kTupleSize<ValuesTuple>) requires(std::move_constructible<R> || std::same_as<R, void>) && (kTupleSize<KeysTuple> == kTupleSize<ValuesTuple>)
{ {
@ -702,14 +715,14 @@ constexpr auto Switch(KeysTuple&& keysTuple, ValuesTuple&& valuesTuple, Key&& ke
}); });
}; };
export template <std::size_t N, typename R = Tuple<>> UTEMPL_EXPORT template <std::size_t N, typename R = Tuple<>>
consteval auto GetIndexesTuple() { consteval auto GetIndexesTuple() {
return [](auto... is) { return [](auto... is) {
return MakeTuple<R>(*is...); return MakeTuple<R>(*is...);
} | kSeq<N>; } | kSeq<N>;
}; };
export template <typename R = Tuple<>, typename... Ts> UTEMPL_EXPORT template <typename R = Tuple<>, typename... Ts>
consteval auto GetTuple(TypeList<Ts...>, TypeList<R> = {}) { consteval auto GetTuple(TypeList<Ts...>, TypeList<R> = {}) {
return MakeTuple<R>(kType<Ts>...); return MakeTuple<R>(kType<Ts>...);
}; };

View file

@ -1,7 +1,6 @@
module;
#include <gtest/gtest.h> #include <gtest/gtest.h>
export module tests.go_interface;
import utempl; #include <utempl/utempl.hpp>
namespace utempl { namespace utempl {

View file

@ -1,7 +1,6 @@
module;
#include <gtest/gtest.h> #include <gtest/gtest.h>
export module tests.overloaded;
import utempl; #include <utempl/utempl.hpp>
namespace utempl { namespace utempl {