diff --git a/lix/libutil/fmt.hh b/lix/libutil/fmt.hh index 8552b97f9..61af0d6cc 100644 --- a/lix/libutil/fmt.hh +++ b/lix/libutil/fmt.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include "lix/libutil/ansicolor.hh" // Explicit instantiation in fmt.cc @@ -11,6 +12,29 @@ extern template class boost::basic_format; namespace nix { +/** Sentinel template struct to mark if a type should automatically generate + * an ostream operator<< based on std::format(). + * + * This template should be specialized to inherit from @ref std::true_type for any type + * that has an @ref std::formatter<> implementation, but not an operator<< implementation. + */ +template +struct LegacyFormat : std::false_type +{}; + +/** Automatically generated ostream operator<< based on @ref std::formatter<> impls. + * + * Only enabled for `T` where @ref std::formatter is specialized, + * @ref nix::LegacyFormat::value is true-ish. + */ +template T> + requires LegacyFormat::value +std::ostream & operator<<(std::ostream & out, T const & self) +{ + out << std::format("{}", self); + return out; +} + /** Gets a C++ stack trace using boost stacktrace */ std::string getStackTrace();