add Chapter18
This commit is contained in:
116
Chapter18/cib/libs/log/env.hpp
Normal file
116
Chapter18/cib/libs/log/env.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdx/compiler.hpp>
|
||||
#include <stdx/ct_string.hpp>
|
||||
#include <stdx/utility.hpp>
|
||||
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
|
||||
namespace logging {
|
||||
template <auto Query, auto Value> struct prop {
|
||||
[[nodiscard]] CONSTEVAL static auto query(decltype(Query)) noexcept {
|
||||
return Value;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename Q, typename Env>
|
||||
concept valid_query_for = requires { Env::query(Q{}); };
|
||||
|
||||
template <typename Q, typename... Envs>
|
||||
concept valid_query_over = (... or valid_query_for<Q, Envs>);
|
||||
|
||||
template <typename Q> struct has_query {
|
||||
template <typename Env>
|
||||
using fn = std::bool_constant<valid_query_for<Q, Env>>;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename... Envs> struct env {
|
||||
template <detail::valid_query_over<Envs...> Q>
|
||||
CONSTEVAL static auto query(Q) noexcept {
|
||||
using I = boost::mp11::mp_find_if_q<boost::mp11::mp_list<Envs...>,
|
||||
detail::has_query<Q>>;
|
||||
using E = boost::mp11::mp_at<boost::mp11::mp_list<Envs...>, I>;
|
||||
return Q{}(E{});
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename T> struct autowrap {
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
CONSTEVAL autowrap(T t) : value(t) {}
|
||||
T value;
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
||||
template <std::size_t N> using str_lit_t = char const (&)[N];
|
||||
|
||||
template <std::size_t N> struct autowrap<str_lit_t<N>> {
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
CONSTEVAL autowrap(str_lit_t<N> str) : value(str) {}
|
||||
stdx::ct_string<N> value;
|
||||
};
|
||||
|
||||
template <typename T> autowrap(T) -> autowrap<T>;
|
||||
template <std::size_t N> autowrap(str_lit_t<N>) -> autowrap<str_lit_t<N>>;
|
||||
|
||||
template <auto V> struct wrap {
|
||||
constexpr static auto value = V;
|
||||
};
|
||||
|
||||
template <typename> struct for_each_pair;
|
||||
template <std::size_t... Is> struct for_each_pair<std::index_sequence<Is...>> {
|
||||
template <auto... Args>
|
||||
using type = env<
|
||||
prop<boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
|
||||
2 * Is>::value.value,
|
||||
stdx::ct<boost::mp11::mp_at_c<boost::mp11::mp_list<wrap<Args>...>,
|
||||
2 * Is + 1>::value.value>()>...>;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename Env = env<>>
|
||||
constexpr auto make_env = []<detail::autowrap... Args> {
|
||||
using new_env_t = typename detail::for_each_pair<
|
||||
std::make_index_sequence<sizeof...(Args) / 2>>::template type<Args...>;
|
||||
return boost::mp11::mp_append<new_env_t, Env>{};
|
||||
};
|
||||
|
||||
template <detail::autowrap... Args>
|
||||
using make_env_t = decltype(make_env<>.template operator()<Args...>());
|
||||
} // namespace logging
|
||||
|
||||
using cib_log_env_t = logging::env<>;
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
|
||||
|
||||
#ifdef __clang__
|
||||
#define CIB_PRAGMA_SEMI
|
||||
#else
|
||||
#define CIB_PRAGMA_SEMI ;
|
||||
#endif
|
||||
|
||||
#define CIB_LOG_ENV_DECL(...) \
|
||||
[[maybe_unused]] typedef decltype([]<logging::detail:: \
|
||||
autowrap... _env_args> { \
|
||||
using new_env_t = \
|
||||
typename logging::detail::for_each_pair<std::make_index_sequence< \
|
||||
sizeof...(_env_args) / 2>>::template type<_env_args...>; \
|
||||
return boost::mp11::mp_append<new_env_t, cib_log_env_t>{}; \
|
||||
}.template operator()<__VA_ARGS__>()) cib_log_env_t
|
||||
|
||||
#define CIB_LOG_ENV(...) \
|
||||
STDX_PRAGMA(diagnostic push) \
|
||||
STDX_PRAGMA(diagnostic ignored "-Wshadow") \
|
||||
CIB_LOG_ENV_DECL(__VA_ARGS__) \
|
||||
CIB_PRAGMA_SEMI \
|
||||
STDX_PRAGMA(diagnostic pop)
|
||||
|
||||
#define CIB_WITH_LOG_ENV(...) \
|
||||
STDX_PRAGMA(diagnostic push) \
|
||||
STDX_PRAGMA(diagnostic ignored "-Wshadow") \
|
||||
if constexpr (CIB_LOG_ENV_DECL(__VA_ARGS__); true) \
|
||||
STDX_PRAGMA(diagnostic pop)
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-macro-usage)
|
||||
Reference in New Issue
Block a user