Remove fmt dependency. Add PublicCast

This commit is contained in:
sha512sum 2024-10-19 23:37:49 +00:00
parent b325c54968
commit 6fa97fcb87
5 changed files with 134 additions and 11 deletions

View file

@ -12,6 +12,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(BOOST_INCLUDE_LIBRARIES "pfr") set(BOOST_INCLUDE_LIBRARIES "pfr")
set(NAMEOF_OPT_INSTALL ON)
option(CPM_USE_LOCAL_PACKAGES "Use local packages" ON) option(CPM_USE_LOCAL_PACKAGES "Use local packages" ON)
option(UTEMPL_MODULE OFF) option(UTEMPL_MODULE OFF)
@ -49,22 +51,24 @@ set(TMP ${CPM_USE_LOCAL_PACKAGES})
set(CPM_USE_LOCAL_PACKAGES OFF) set(CPM_USE_LOCAL_PACKAGES OFF)
CPMAddPackage( CPMAddPackage(
NAME fmt NAME nameof
URL URL
"https://github.com/fmtlib/fmt/releases/download/11.0.2/fmt-11.0.2.zip" "https://helicopter.myftp.org/git/sha512sum/nameof_module/archive/master.tar.gz"
EXCLUDE_FROM_ALL ON EXCLUDE_FROM_ALL ON
OPTIONS "FMT_MODULE ON" OPTIONS "NAMEOF_MODULE ON"
) )
set(CPM_USE_LOCAL_PACKAGES ${TMP}) set(CPM_USE_LOCAL_PACKAGES ${TMP})
else() else()
CPMAddPackage("gh:fmtlib/fmt#11.0.2") CPMAddPackage("gh:Neargye/nameof@0.10.4")
endif() endif()
cmake_policy(SET CMP0079 NEW) cmake_policy(SET CMP0079 NEW)
include(GNUInstallDirs) include(GNUInstallDirs)
@ -106,11 +110,11 @@ if(UTEMPL_MODULE)
endif() endif()
endforeach() endforeach()
if(TARGET Boost::pfr) if(TARGET Boost::pfr)
target_link_libraries(utempl PUBLIC fmt::fmt target_link_libraries(utempl PUBLIC nameof::nameof
Boost::pfr) Boost::pfr)
else() else()
find_package(Boost 1.85.0 REQUIRED) find_package(Boost 1.85.0 REQUIRED)
target_link_libraries(utempl PUBLIC fmt::fmt target_link_libraries(utempl PUBLIC nameof::nameof
${Boost_LIBRARIES}) ${Boost_LIBRARIES})
endif() endif()
target_include_directories(utempl PUBLIC target_include_directories(utempl PUBLIC
@ -146,12 +150,12 @@ else()
endif() endif()
endforeach() endforeach()
if(TARGET Boost::pfr) if(TARGET Boost::pfr)
target_link_libraries(utempl INTERFACE fmt::fmt target_link_libraries(utempl INTERFACE nameof::nameof
Boost::pfr) Boost::pfr nameof::nameof)
else() else()
find_package(Boost 1.85.0 REQUIRED) find_package(Boost 1.85.0 REQUIRED)
target_link_libraries(utempl INTERFACE fmt::fmt target_link_libraries(utempl INTERFACE nameof::nameof
${Boost_LIBRARIES}) ${Boost_LIBRARIES} nameof::nameof)
endif() endif()
target_include_directories(utempl INTERFACE target_include_directories(utempl INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/_headers> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/_headers>

View file

@ -0,0 +1,38 @@
#include <utempl/utempl.hpp>
using namespace utempl; // NOLINT
struct A {
private:
[[nodiscard]] constexpr auto Method() const -> int {
return 1;
};
[[nodiscard]] constexpr auto Method(int) const -> int {
return 2;
};
[[nodiscard]] constexpr auto Method() -> int {
return 3;
};
};
namespace utempl {
template struct PublicCast<static_cast<int (A::*)() const>(&A::Method)>;
template struct PublicCast<static_cast<int (A::*)(int) const>(&A::Method)>;
template struct PublicCast<static_cast<int (A::*)()>(&A::Method)>;
} // namespace utempl
constexpr A a;
static_assert(GetPrivateMemberOverloaded<"Method">(a) == 1);
static_assert(GetPrivateMemberOverloaded<"Method">(a, 1) == 2);
static_assert(GetPrivateMemberOverloaded<"Method">(A{}) == 3);
static_assert((a.*GetPrivateMember<"Method", 0, A>())() == 1);
static_assert((a.*GetPrivateMember<"Method", 1>(a))(1) == 2);
auto main() -> int {};

80
src/public_cast.cpp Normal file
View file

@ -0,0 +1,80 @@
#pragma once
#include <utempl/module.hpp>
#ifdef UTEMPL_MODULE
export module utempl.public_cast;
import utempl.loopholes;
import std;
import utempl.overloaded;
import utempl.string;
import nameof;
#else
#include <nameof.hpp>
#include <utempl/loopholes/counter.hpp>
#include <utempl/overloaded.hpp>
#endif
namespace utempl {
namespace impl { // For headers
template <typename T, ConstexprString Str>
struct PublicCast {
template <std::size_t I>
struct Tag {};
};
template <typename Ptr>
using MainT = decltype(Overloaded([]<typename T, typename R, typename... Args>(R (T::*ptr)(Args...)) -> T {},
[]<typename T, typename R, typename... Args>(R (T::*ptr)(Args...) const) -> T {},
[]<typename T, typename R>(R T::* ptr) -> T {})(std::declval<Ptr>()));
template <auto ptr>
constexpr auto TransformPtr() {
return utempl::Overloaded(
[]<typename T, typename R, typename... Args>(R (T::*)(Args...)) {
return [](T* obj, Args... args) -> R {
return (obj->*ptr)(std::forward<Args>(args)...);
};
},
[]<typename T, typename R, typename... Args>(R (T::*)(Args...) const) {
return [](const T* obj, Args... args) -> R {
return (obj->*ptr)(std::forward<Args>(args)...);
};
})(ptr);
};
} // namespace impl
UTEMPL_EXPORT template <auto Ptr,
auto F = [] {},
typename T = impl::MainT<decltype(Ptr)>,
ConstexprString Str =
utempl::ConstexprString<nameof::nameof_member<Ptr>().size() + 1>{nameof::nameof_member<Ptr>()},
typename Tag = impl::PublicCast<T, Str>,
auto I = loopholes::Counter<Tag, decltype(F)>(),
auto = loopholes::Injector<typename Tag::template Tag<I>{}, Ptr>{}>
struct PublicCast {};
UTEMPL_EXPORT template <ConstexprString Name, std::size_t I = 0, typename T>
constexpr auto GetPrivateMember() -> decltype(Magic(loopholes::Getter<typename impl::PublicCast<T, Name>::template Tag<I>{}>{})) {
return Magic(loopholes::Getter<typename impl::PublicCast<T, Name>::template Tag<I>{}>{});
}
UTEMPL_EXPORT template <ConstexprString Name, std::size_t I = 0, typename T>
constexpr auto GetPrivateMember(const T&) -> decltype(GetPrivateMember<Name, I, std::decay_t<T>>()) {
return GetPrivateMember<Name, I, std::decay_t<T>>();
}
UTEMPL_EXPORT template <utempl::ConstexprString Name, typename T, auto F = [] {}, typename... Args>
constexpr auto GetPrivateMemberOverloaded(T&& obj, Args&&... args) -> decltype(auto) {
return [&]<std::size_t... Is>(std::index_sequence<Is...>) -> decltype(auto) {
return Overloaded(impl::TransformPtr<GetPrivateMember<Name, Is, std::decay_t<T>>()>()...)(std::addressof(obj),
std::forward<Args>(args)...);
}(std::make_index_sequence<loopholes::CountValue<impl::PublicCast<std::decay_t<T>, Name>, decltype(F)>()>());
};
} // namespace utempl

View file

@ -13,6 +13,7 @@ export import utempl.overloaded;
export import utempl.utils; export import utempl.utils;
export import utempl.go_interface; export import utempl.go_interface;
export import utempl.optional; export import utempl.optional;
export import utempl.public_cast;
#else #else
#include <utempl/attributes.hpp> #include <utempl/attributes.hpp>
@ -23,6 +24,7 @@ export import utempl.optional;
#include <utempl/meta_info.hpp> #include <utempl/meta_info.hpp>
#include <utempl/optional.hpp> #include <utempl/optional.hpp>
#include <utempl/overloaded.hpp> #include <utempl/overloaded.hpp>
#include <utempl/public_cast.hpp>
#include <utempl/tuple.hpp> #include <utempl/tuple.hpp>
#include <utempl/type_list.hpp> #include <utempl/type_list.hpp>

View file

@ -5,7 +5,6 @@
#ifdef UTEMPL_MODULE #ifdef UTEMPL_MODULE
export module utempl.utils; export module utempl.utils;
import std; import std;
import fmt;
import utempl.string; import utempl.string;
import utempl.tuple; import utempl.tuple;
import utempl.type_list; import utempl.type_list;