diff --git a/.gitignore b/.gitignore index 7da542b..c32e6a6 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,5 @@ utemplConfigVersion.cmake utempl_tests utempl_tests\[1\]_include.cmake utempl_tests\[1\]_tests.cmake -libutempl_shared.so -libutempl_static.so +libutempl.a +_headers diff --git a/CMakeLists.txt b/CMakeLists.txt index 04a9664..137efb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,10 +12,17 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_MODULE_STD 1) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(FMT_MODULE ON) set(BOOST_INCLUDE_LIBRARIES "pfr") 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") set_target_properties(__cmake_cxx23 PROPERTIES CXX_EXTENSIONS OFF) @@ -38,6 +45,8 @@ CPMAddPackage( OPTIONS "BOOST_SKIP_INSTALL_RULES OFF" ) +if(UTEMPL_MODULE) + set(TMP ${CPM_USE_LOCAL_PACKAGES}) set(CPM_USE_LOCAL_PACKAGES OFF) @@ -45,29 +54,93 @@ CPMAddPackage( NAME fmt URL "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 ) set(CPM_USE_LOCAL_PACKAGES ${TMP}) +else() +CPMAddPackage("gh:fmtlib/fmt#11.0.2") + + +endif() cmake_policy(SET CMP0079 NEW) 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) target_compile_features(utempl INTERFACE cxx_std_23) -target_include_directories(utempl INTERFACE $ - $) +target_include_directories(utempl INTERFACE + $ + $) -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" 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() file(GLOB SOURCES tests/* tests/*/* tests/*/*/*) add_executable(utempl_tests) - target_sources(utempl_tests PUBLIC FILE_SET utempl_tests TYPE CXX_MODULES - FILES ${SOURCES}) + target_sources(utempl_tests PUBLIC ${SOURCES}) target_link_libraries(utempl_tests GTest::gtest_main utempl::utempl) set_property(TARGET utempl_tests PROPERTY CXX_STANDARD 23) include(GoogleTest) diff --git a/examples/src/attributes.cpp b/examples/src/attributes.cpp index 310ee68..78ef18e 100644 --- a/examples/src/attributes.cpp +++ b/examples/src/attributes.cpp @@ -1,6 +1,6 @@ -import std; -import utempl; +#include #include +import std; template struct AttributeData { diff --git a/examples/src/curry.cpp b/examples/src/curry.cpp index 6a8eacd..f51c9c2 100644 --- a/examples/src/curry.cpp +++ b/examples/src/curry.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/go_interface.cpp b/examples/src/go_interface.cpp index 2f55bcb..f062b5d 100644 --- a/examples/src/go_interface.cpp +++ b/examples/src/go_interface.cpp @@ -1,5 +1,4 @@ -import fmt; -import utempl; +#include import std; struct SomeInterfaceImpl { @@ -13,7 +12,7 @@ struct SomeStruct { }; inline auto Func(SomeInterface arg) { - fmt::print("{} {}\n", arg.a, arg.b); + std::println("{} {}\n", arg.a, arg.b); }; auto main() -> int { diff --git a/examples/src/left_fold.cpp b/examples/src/left_fold.cpp index 5395c11..3986e7e 100644 --- a/examples/src/left_fold.cpp +++ b/examples/src/left_fold.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/make.cpp b/examples/src/make.cpp index bfe4b24..25630e7 100644 --- a/examples/src/make.cpp +++ b/examples/src/make.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/meta.cpp b/examples/src/meta.cpp index 4e7f934..5e0b1af 100644 --- a/examples/src/meta.cpp +++ b/examples/src/meta.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/overloaded.cpp b/examples/src/overloaded.cpp index d244a8d..03f848c 100644 --- a/examples/src/overloaded.cpp +++ b/examples/src/overloaded.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/pipe.cpp b/examples/src/pipe.cpp index affe128..2b8085c 100644 --- a/examples/src/pipe.cpp +++ b/examples/src/pipe.cpp @@ -1,4 +1,4 @@ -import utempl; +#include struct Container { float data{}; diff --git a/examples/src/reverse.cpp b/examples/src/reverse.cpp index 969e153..4b1b33a 100644 --- a/examples/src/reverse.cpp +++ b/examples/src/reverse.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/switch.cpp b/examples/src/switch.cpp index 6b5b104..95a399d 100644 --- a/examples/src/switch.cpp +++ b/examples/src/switch.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/times.cpp b/examples/src/times.cpp index c5d226a..6c868fe 100644 --- a/examples/src/times.cpp +++ b/examples/src/times.cpp @@ -1,4 +1,4 @@ -import utempl; +#include import std; auto main() -> int { diff --git a/examples/src/tuple.cpp b/examples/src/tuple.cpp index ab2537a..5fae143 100644 --- a/examples/src/tuple.cpp +++ b/examples/src/tuple.cpp @@ -1,5 +1,5 @@ #include -import utempl; +#include import std; auto main() -> int { diff --git a/src/attributes.cpp b/src/attributes.cpp index 4756b80..b097d66 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -1,54 +1,66 @@ +#pragma once +#include + +#ifdef UTEMPL_MODULE export module utempl.attributes; export import utempl.meta_info; export import utempl.tuple; export import utempl.loopholes.counter; import utempl.utils; import utempl.type_list; +#else + +#include +#include +#include +#include +#include +#endif namespace utempl { namespace impl { -export struct AttributesTag {}; +UTEMPL_EXPORT struct AttributesTag {}; -export template +UTEMPL_EXPORT template struct AttributesCounterTag {}; } // namespace impl -export template ()> +UTEMPL_EXPORT template ()> consteval auto OpenStruct() -> bool { return true; }; -export template (), - auto II = (I >= 2) ? I - 2 : I - 1, - typename T = decltype(Magic(loopholes::Getter{}>{}))::Type, - auto = AddTypeToTag()> +UTEMPL_EXPORT template (), + auto II = (I >= 2) ? I - 2 : I - 1, + typename T = decltype(Magic(loopholes::Getter{}>{}))::Type, + auto = AddTypeToTag()> consteval auto CloseStruct() -> bool { return true; }; -export struct NoInfo { +UTEMPL_EXPORT struct NoInfo { consteval auto operator==(const NoInfo&) const -> bool = default; }; -export template , - auto f = [] {}, - typename Current = decltype(GetCurrentTagType())::Type, - auto = AddTypeToTag, O, decltype(f)>()> +UTEMPL_EXPORT template , + auto f = [] {}, + typename Current = decltype(GetCurrentTagType())::Type, + auto = AddTypeToTag, O, decltype(f)>()> using FieldAttribute = T; -export template , decltype(f)>() > 0)> +UTEMPL_EXPORT template , decltype(f)>() > 0)> concept HasAttributes = R; -export template +UTEMPL_EXPORT template concept HasMacroAttributes = requires { T::template GetAttribute<0>(); }; -export template +UTEMPL_EXPORT template consteval auto GetAttributes() requires HasMacroAttributes { @@ -58,7 +70,7 @@ consteval auto GetAttributes() } | kSeq; }; -export template +UTEMPL_EXPORT template consteval auto GetAttributes() { constexpr auto I = loopholes::CountValue>(); return diff --git a/src/constexpr_string.cpp b/src/constexpr_string.cpp index 910aecc..d9628a6 100644 --- a/src/constexpr_string.cpp +++ b/src/constexpr_string.cpp @@ -1,9 +1,16 @@ +#pragma once +#include +#ifdef UTEMPL_MODULE export module utempl.string; import std; -// import fmt; +#else +#include +#include +#endif -export namespace utempl { +UTEMPL_EXPORT_BEGIN +namespace utempl { template struct ConstexprString { std::array data; @@ -78,3 +85,5 @@ constexpr auto CreateStringWith(char c) { template ConstexprString(const char (&data)[Size]) -> ConstexprString; // NOLINT } // namespace utempl + +UTEMPL_EXPORT_END diff --git a/src/go_interface.cpp b/src/go_interface.cpp index 07d441c..b2ef7f7 100644 --- a/src/go_interface.cpp +++ b/src/go_interface.cpp @@ -1,9 +1,21 @@ +#pragma once +#include + +#ifdef UTEMPL_MODULE + module; #include export module utempl.go_interface; import std; import utempl.string; +#else + +#include +#include + +#endif + namespace utempl { template @@ -40,7 +52,7 @@ constexpr auto Transform(Transformer&& transformer, From&& from) { }(std::make_index_sequence>()); }; -export struct DefaultFieldTransformer { +UTEMPL_EXPORT struct DefaultFieldTransformer { constexpr auto operator()(auto&& arg) -> auto&& { return arg; }; @@ -53,7 +65,7 @@ export struct DefaultFieldTransformer { }; }; -export template +UTEMPL_EXPORT template struct GoInterface : Value { constexpr GoInterface(Value&& value) : Value(std::move(value)) {}; // NOLINT constexpr GoInterface(const Value& value) : Value(value) {}; // NOLINT diff --git a/src/loopholes/core.cpp b/src/loopholes/core.cpp index 37947a4..8d2bf71 100644 --- a/src/loopholes/core.cpp +++ b/src/loopholes/core.cpp @@ -1,20 +1,32 @@ +#pragma once + +#include + +#ifdef UTEMPL_MODULE + export module utempl.loopholes.core; import std; +#else + +#include + +#endif + namespace utempl::loopholes { -export { - template - struct Getter { - friend constexpr auto Magic(Getter); +UTEMPL_EXPORT_BEGIN +template +struct Getter { + friend constexpr auto Magic(Getter); +}; +template +struct Injector { + friend constexpr auto Magic(Getter) { + return Value; }; - template - struct Injector { - friend constexpr auto Magic(Getter) { - return Value; - }; - }; -} +}; +UTEMPL_EXPORT_END template struct InjectedImpl { static constexpr bool value = false; @@ -24,7 +36,7 @@ struct InjectedImpl{}))>, Ts...> { static constexpr bool value = true; }; -export template +UTEMPL_EXPORT template concept Injected = InjectedImpl::value; } // namespace utempl::loopholes diff --git a/src/loopholes/counter.cpp b/src/loopholes/counter.cpp index 00f0851..d40e017 100644 --- a/src/loopholes/counter.cpp +++ b/src/loopholes/counter.cpp @@ -1,7 +1,21 @@ +#pragma once + +#include + +#ifdef UTEMPL_MODULE + export module utempl.loopholes.counter; export import utempl.loopholes.core; import std; + +#else + +#include +#include + +#endif + namespace utempl::loopholes { template diff --git a/src/loopholes/loopholes.cpp b/src/loopholes/loopholes.cpp index 6bebbe0..60cdee2 100644 --- a/src/loopholes/loopholes.cpp +++ b/src/loopholes/loopholes.cpp @@ -1,3 +1,11 @@ +#pragma once +#ifdef UTEMPL_MODULE + export module utempl.loopholes; export import utempl.loopholes.core; export import utempl.loopholes.counter; + +#else +#include +#include +#endif diff --git a/include/utempl/macro.hpp b/src/macro.hpp similarity index 100% rename from include/utempl/macro.hpp rename to src/macro.hpp diff --git a/src/meta_info.cpp b/src/meta_info.cpp index 56a58ee..1fe243e 100644 --- a/src/meta_info.cpp +++ b/src/meta_info.cpp @@ -1,16 +1,23 @@ +#pragma once +#ifdef UTEMPL_MODULE export module utempl.meta_info; import utempl.loopholes; import utempl.type_list; import std; +#else +#include +#include +#include +#endif namespace utempl { -export struct Types {}; +UTEMPL_EXPORT struct Types {}; -export template +UTEMPL_EXPORT template struct MetaInfoKey {}; -export template +UTEMPL_EXPORT template struct MetaInfo { static constexpr std::size_t kTypeId = loopholes::Counter(); using Type = T; @@ -19,23 +26,23 @@ struct MetaInfo { static constexpr auto _ = loopholes::Injector{}, TypeList{}>{}; }; -export template +UTEMPL_EXPORT template inline constexpr std::size_t kTypeId = MetaInfo::kTypeId; -export template (), - auto = loopholes::Injector{}, TypeList{}>{}> +UTEMPL_EXPORT template (), + auto = loopholes::Injector{}, TypeList{}>{}> consteval auto AddTypeToTag(TTs&&...) -> std::size_t { return Id; }; -export template +UTEMPL_EXPORT template using GetMetaInfo = MetaInfo{}>{}))::Type>; -export template +UTEMPL_EXPORT template using GetType = GetMetaInfo::Type; template @@ -55,12 +62,12 @@ static consteval auto GetTypeListForTag(G g) }; }; -export template +UTEMPL_EXPORT template consteval auto GetTypeListForTag() { return GetTypeListForTag(TypeList{}); }; -export template () - 1> +UTEMPL_EXPORT template () - 1> consteval auto GetCurrentTagType() { return Magic(utempl::loopholes::Getter{}>()); }; diff --git a/src/optional.cpp b/src/optional.cpp index 3fe6b68..0007e30 100644 --- a/src/optional.cpp +++ b/src/optional.cpp @@ -1,9 +1,18 @@ +#pragma once +#include +#ifdef UTEMPL_MODULE export module utempl.optional; import std; +#else + +#include + +#endif + namespace utempl { -export template +UTEMPL_EXPORT template struct Optional { // NOLINT bool flag = false; union { diff --git a/src/overloaded.cpp b/src/overloaded.cpp index 242330d..3d4ce1b 100644 --- a/src/overloaded.cpp +++ b/src/overloaded.cpp @@ -1,8 +1,16 @@ +#pragma once +#include + +#ifdef UTEMPL_MODULE export module utempl.overloaded; import std; +#else +#include +#endif + namespace utempl { -export template +UTEMPL_EXPORT template constexpr auto Overloaded(Fs&&... fs) { struct Overloaded : public std::remove_cvref_t... { using Fs::operator()...; diff --git a/src/tuple.cpp b/src/tuple.cpp index 59e2f80..7eda00d 100644 --- a/src/tuple.cpp +++ b/src/tuple.cpp @@ -1,12 +1,21 @@ +#pragma once + +#include +#ifdef UTEMPL_MODULE + export module utempl.tuple; import utempl.type_list; import utempl.overloaded; import std; +#else +#include +#include +#endif namespace utempl { -export template +UTEMPL_EXPORT template struct Wrapper { static constexpr auto kValue = Value; static constexpr auto value = Value; @@ -35,10 +44,10 @@ struct TupleHelper, Ts...> : public TupleLeaf constexpr auto operator==(const TupleHelper&) const -> bool = default; }; -export template +UTEMPL_EXPORT template struct Tuple; -export template +UTEMPL_EXPORT template constexpr auto Get(Tuple& tuple) -> auto& requires(I < sizeof...(Ts)) { @@ -46,7 +55,7 @@ constexpr auto Get(Tuple& tuple) -> auto& return static_cast&>(tuple).value; }; -export template +UTEMPL_EXPORT template constexpr auto Get(const Tuple& tuple) -> const auto& requires(I < sizeof...(Ts)) { @@ -54,7 +63,7 @@ constexpr auto Get(const Tuple& tuple) -> const auto& return static_cast&>(tuple).value; }; -export template +UTEMPL_EXPORT template constexpr auto Get(Tuple&& tuple) -> decltype(auto) requires(I < sizeof...(Ts)) { @@ -62,12 +71,12 @@ constexpr auto Get(Tuple&& tuple) -> decltype(auto) return std::move(static_cast&&>(tuple).value); }; -export template +UTEMPL_EXPORT template constexpr auto Get(T&& arg) -> decltype(get(std::forward(arg))) { return get(std::forward(arg)); }; -export template +UTEMPL_EXPORT template struct Tuple : TupleHelper, Ts...> { template constexpr Tuple(TTs&&... args) /* NOLINT */ : TupleHelper, Ts...>{{std::forward(args)}...} {}; @@ -106,7 +115,7 @@ struct Tuple : TupleHelper, Ts...> { }; }; -export template <> +UTEMPL_EXPORT template <> struct Tuple<> { template constexpr auto operator+(const Tuple& other) const -> Tuple { @@ -116,10 +125,10 @@ struct Tuple<> { return true; }; }; -export template +UTEMPL_EXPORT template Tuple(Ts&&...) -> Tuple...>; -export template +UTEMPL_EXPORT template consteval auto ListFromTuple(Tuple) -> TypeList { return {}; }; diff --git a/src/type_list.cpp b/src/type_list.cpp index deed029..a4eb070 100644 --- a/src/type_list.cpp +++ b/src/type_list.cpp @@ -1,25 +1,36 @@ +#pragma once + +#include +#ifdef UTEMPL_MODULE + export module utempl.type_list; import std; import utempl.overloaded; +#else + +#include +#include + +#endif namespace utempl { -export template +UTEMPL_EXPORT template struct TypeList {}; -export template +UTEMPL_EXPORT template struct TypeList { using Type = T; }; -export template +UTEMPL_EXPORT template inline constexpr auto kType = TypeList{}; -export template +UTEMPL_EXPORT template inline constexpr auto kTypeList = TypeList{}; -export template +UTEMPL_EXPORT template concept IsTypeList = Overloaded( [](TypeList>) { return true; @@ -37,45 +48,45 @@ struct Caster {}; template struct Caster, Ts...> : IndexedType... {}; -export template +UTEMPL_EXPORT template consteval auto operator==(const TypeList& first, const TypeList& second) -> bool { return std::same_as; }; -export template +UTEMPL_EXPORT template consteval auto operator+(const TypeList&, const TypeList&) -> TypeList { return {}; }; -export template +UTEMPL_EXPORT template consteval auto Get(TypeList) -> decltype([](IndexedType&&) -> T { }(Caster, Ts...>{})); -export template +UTEMPL_EXPORT template consteval auto Find(TypeList) -> std::size_t { std::array arr{std::same_as...}; return std::ranges::find(arr, true) - arr.begin(); }; -export template