#pragma once #include #include "mcc_concepts.h" #include "mcc_traits.h" namespace mcc { struct mcc_serializer_interface_t { virtual ~mcc_serializer_interface_t() = default; template SelfT, traits::mcc_output_char_range R, typename ValueT, typename FmtT = std::format_string> requires(std::same_as> || std::same_as) mcc_error_c auto operator()(this SelfT&& self, R& output, ValueT&& value, FmtT fmt = "{}") { return std::forward(self).operator=(output, std::forward(value), std::move(fmt)); } }; template concept mcc_serializer_c = std::derived_from; template class MccSerializer; template class MccSerializer : public mcc_serializer_interface_t { public: static constexpr std::string_view defaultDelimiter{","}; typedef std::error_code error_t; MccSerializer() = default; ~MccSerializer() = default; template > error_t operator()(traits::mcc_output_char_range auto& output, VT&& value, FmtT fmt = "{}") requires std::formattable { if constexpr (std::same_as>) { std::format_to(std::back_inserter(output), fmt, value); } else if constexpr (std::same_as) { std::vformat_to(std::back_inserter(output), fmt, std::make_format_args(value)); } return {}; } protected: std::string _delimiter{defaultDelimiter}; }; template class MccSerializer : public mcc_serializer_interface_t { public: error_t operator()(traits::mcc_output_char_range auto& output, T&& value) { std::format_to(std::back_inserter(output), "{}", value.degrees()); return {}; } }; static_assert(mcc_serializer_c>, "!!!"); static_assert(mcc_serializer_c>, "!!!"); void f() { MccSerializer s; std::string str; s(str, impl::MccAngleALT{1.1}); } } // namespace mcc