#pragma once #if not __cplusplus >= 202002L # error "csl/ag.hpp requires C++20" #endif #include #include #include #include #include #include #include #include #include #define csl_fwd(...) static_cast(__VA_ARGS__) // NOLINT(cppcoreguidelines-macro-usage) namespace csl::ag::details::unevaluated { // to use in an unevaluated context only template consteval auto declval() noexcept -> std::add_rvalue_reference_t { // static_assert([](){ return false; }(), "csl::ag::details : declval : for unevaluated context only !"); if constexpr (std::is_lvalue_reference_v) return *((std::remove_reference_t *)(nullptr)); else return std::move(*((std::remove_reference_t *)(nullptr))); } struct ref_evaluator { explicit constexpr ref_evaluator() = delete; constexpr ~ref_evaluator() = delete; constexpr ref_evaluator(const ref_evaluator&) = delete; constexpr ref_evaluator(ref_evaluator&&) = delete; constexpr ref_evaluator & operator=(const ref_evaluator&) = delete; constexpr ref_evaluator & operator=(ref_evaluator&&) = delete; // Implicit conversion // not `return std::declval();`, as clang does not like it even in a non-evaluated context // neither `consteval` -> Clang-16.0.? ICE template [[nodiscard]] consteval operator T&&() const noexcept { // NOLINT(google-explicit-constructor) return declval(); } template [[nodiscard]] consteval operator T&() const noexcept { // NOLINT(google-explicit-constructor) return declval(); } }; } namespace csl::ag::details::mp { // NTTP-dependent type template struct unfolder : std::type_identity{}; template using unfolder_t = typename unfolder::type; // P1450 Enriching type modification traits : https://github.com/cplusplus/papers/issues/216 // Note that this is a good-enough implementation of P1450 to only fit this project's needs // P1450 copy_ref template struct copy_ref : std::remove_reference{}; template struct copy_ref : std::add_lvalue_reference{}; template struct copy_ref : std::add_rvalue_reference>{}; template using copy_ref_t = typename copy_ref::type; // P1450 - add cv - impl detail (also for ref-qualified types) template struct add_const : std::type_identity{}; template struct add_const : std::type_identity{}; template struct add_const : std::type_identity{}; template using add_const_t = typename add_const::type; template struct add_volatile : std::type_identity{}; template struct add_volatile : std::type_identity{}; template struct add_volatile : std::type_identity{}; template using add_volatile_t = typename add_volatile::type; template struct add_cv : add_const::type>{}; template using add_cv_t = typename add_cv::type; // P1450 copy_cv template struct copy_cv : std::remove_cv{}; template requires (std::is_reference_v) struct copy_cv : copy_cv, to>{}; template struct copy_cv : add_cv{}; template struct copy_cv : add_const{}; template struct copy_cv : add_volatile{}; template using copy_cv_t = typename copy_cv::type; // P1450 copy_cvref template struct copy_cvref : copy_cv>{}; template using copy_cvref_t = typename copy_cvref::type; // field_view template struct field_view : copy_cvref{}; template requires (std::is_reference_v) struct field_view : std::type_identity{}; template using field_view_t = typename field_view::type; // bind_front // TODO: remove ? template