#pragma once #include #include namespace xrpl { class STAmount; class Asset; class Issue; class MPTIssue; class IOUAmount; class XRPAmount; class MPTAmount; template concept StepAmount = std::is_same_v || std::is_same_v || std::is_same_v; template concept ValidIssueType = std::is_same_v || std::is_same_v; template concept AssetType = std::is_convertible_v || std::is_convertible_v || std::is_convertible_v || std::is_convertible_v; template concept ValidPathAsset = (std::is_same_v || std::is_same_v); template concept ValidTaker = ((std::is_same_v || std::is_same_v || std::is_same_v) && (std::is_same_v || std::is_same_v || std::is_same_v) && (!std::is_same_v || !std::is_same_v)); namespace detail { // This template combines multiple callable objects (lambdas) into a single // object that std::visit can use for overload resolution. template struct CombineVisitors : Ts... { // Bring all operator() overloads from base classes into this scope. // It's the mechanism that makes the CombineVisitors struct function // as a single callable object with multiple overloads. using Ts::operator()...; // Perfect forwarding constructor to correctly initialize the base class // lambdas constexpr CombineVisitors(Ts&&... ts) : Ts(std::forward(ts))... { } }; // This function forces function template argument deduction, which is more // robust than class template argument deduction (CTAD) via the deduction guide. template constexpr CombineVisitors...> make_combine_visitors(Ts&&... ts) { // std::decay_t is used to remove references/constness from the lambda // types before they are passed as template arguments to the CombineVisitors // struct. return CombineVisitors...>{std::forward(ts)...}; } // This function takes ANY variant and ANY number of visitors, and performs the // visit. It is the reusable core logic. template constexpr auto visit(Variant&& v, Visitors&&... visitors) -> decltype(auto) { // Use the function template helper instead of raw CTAD. auto visitor_set = make_combine_visitors(std::forward(visitors)...); // Delegate to std::visit, perfectly forwarding the variant and the visitor // set. return std::visit(visitor_set, std::forward(v)); } } // namespace detail } // namespace xrpl