标签: fmt

FMT C ++库:允许用户为自定义类型设置格式说明符

例如,我有一个自定义类型

struct custom_type
{
    double value;
};
Run Code Online (Sandbox Code Playgroud)

我想为此类型设置自定义FMT格式器。我执行以下操作,并且有效:

namespace fmt
{
    template <>
    struct formatter<custom_type> {
        template <typename ParseContext>
        constexpr auto parse(ParseContext &ctx) {
        return ctx.begin();
    };

    template <typename FormatContext>
    auto format(const custom_type &v, FormatContext &ctx) {
        return format_to(ctx.begin(), "{}", v.value);
    }
};
Run Code Online (Sandbox Code Playgroud)

但是问题是,输出格式是由带有此"{}"表达式的模板代码设置的。我想给用户一个机会自己定义格式字符串。

例如:

custom_type v = 10.0;
std::cout << fmt::format("{}", v) << std::endl;    // 10
std::cout << fmt::format("{:+f}", v) << std::endl; // 10.000000
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

目前,当我设置自定义格式字符串时,

 what():  unknown format specifier
Run Code Online (Sandbox Code Playgroud)

c++ fmt

9
推荐指数
1
解决办法
321
查看次数

如何测试控制台是否支持 ANSI 颜色代码?

我使用基于 fmt 的记录器以及可选的彩色打印 - 它依赖于 ANSI 颜色命令。

不幸的是,在 Windows 10 上它默认被禁用。我知道如何启用它,但我仍然想知道如何测试控制台是否支持 ANSI 命令。有人知道吗?

c++ windows terminal ansi-colors fmt

9
推荐指数
1
解决办法
3601
查看次数

fmt 格式 %H:%M:%S 不带小数

我正在尝试将std::chrono::duration对象格式化为 HH:MM::SS 格式,例如 16:42:02 是小时 (16)、分钟 (42) 和秒 (2)。

该库fmt为此提供了有用的格式说明符:

using namespace std::chrono;

auto start = high_resolution_clock::now();
auto end = start + 4s;
fmt::print("{:%H:%M:%S} \n", end);
Run Code Online (Sandbox Code Playgroud)

不幸的是,它以小数形式打印秒

16:58:55.359425076 
Run Code Online (Sandbox Code Playgroud)

我想将其四舍五入到最接近的整数,但无法弄清楚在哪里放置精度说明符(精度 2 仅在测试方面):

fmt::print("{:.2%H:%M:%S} \n", end);  // error
fmt::print("{:.2f%H:%M:%S} \n", end);  // error 
fmt::print("{:%H:%M:.2%S} \n", end);  // nonsense: 17:07:.202.454873454 
Run Code Online (Sandbox Code Playgroud)

我盯着chrono 格式规范的细节有点迷失......

上面的编译器资源管理器示例在这里

c++ formatting c++-chrono c++20 fmt

9
推荐指数
1
解决办法
427
查看次数

使用 {fmt} 库打印

我可以使用fmt库打印 C++ 类的对象吗?

fmt::print("The object is {}.", obj);
Run Code Online (Sandbox Code Playgroud)

c++ fmt

8
推荐指数
2
解决办法
9681
查看次数

如何使用 std::format 格式化同一基类的所有派生类?

我有很多从同一个基类派生的类,并且我试图避免为所有派生类编写格式化程序。我尝试只为基类实现 std::formatter,但将派生类对象/引用传递给 std::format 将触发编译错误。

C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\format(1496): 错误 C2665: 'std::_Format_arg_traits<_Context>::_Phony_basic_format_arg_constructor': 没有5 个重载可以使用 [ _Context=std::format_context ] 转换所有参数类型...

最小代码如下:

#include <format>
#include <iostream>
#include <string>

using namespace std;

struct Base
{
    virtual string ToString()
    {
        return "Base";
    }
};

struct D1 : public Base
{
    string ToString() override
    {
        return "D1";
    }
};

template <typename CharT> struct ::std::formatter<Base, CharT> : ::std::formatter<::std::string>
{
    // parse is inherited from formatter<string>.
    template <typename FormatContext> auto format(Base &e, FormatContext &ctx) const
    {
        ::std::string name = …
Run Code Online (Sandbox Code Playgroud)

c++ formatting c++20 fmt

8
推荐指数
1
解决办法
627
查看次数

用户定义类型的 std::format ?

在 C++20 中 - 如何使用户定义的类型与 兼容std::format

例如,假设我有一个名为 的类型Point

struct Point {
    int x;
    int y;
};
Run Code Online (Sandbox Code Playgroud)

operator<<定义:

inline std::ostream&
operator<<(std::ostream& o, Point pt)
{ return o << "[" << pt.x << << ", " << pt.y << "]"; }
Run Code Online (Sandbox Code Playgroud)

那么下面的程序会输出Hello [3, 4]!吗?

int main() {
   Point pt{3,4};
   std::cout << std::format("Hello {}!\n", pt);
}
Run Code Online (Sandbox Code Playgroud)

如果是 - 为什么以及如何?

如果不是 - 我必须在 to 的定义中添加什么Point才能使其工作?

c++ c++20 fmt

7
推荐指数
2
解决办法
734
查看次数

libfmt 和 std::format 之间有什么区别?

我知道 c++20 格式提案是libfmt部分的形式化,而 libfmt 是该形式化的兼容实现。但是,据我所知,libfmt 提供的功能超出了 c++20 标准中指定的功能。有哪些附加功能?

另外,主要编译器供应商是简单地包含 libfmt 的一个子集还是重新实现它?

c++ c++20 fmt

7
推荐指数
1
解决办法
757
查看次数

使用 {fmt} 和 source_location 创建基于可变参数模板的日志功能

我想在 C++ 中创建一个简单的日志函数,它将代码位置添加到日志消息中。我想避免使用宏以及__FILE__&的使用__LINE__

请注意,该format字符串始终是编译时字符串,我希望在编译时进行尽可能多的计算(目标机器是一个小型 MCU)。

我可以source_location通过experimental/source_location. 我也可以使用{fmt}

我从这个开始。目前,我有以下几点:

#include <fmt/format.h>
#include <experimental/source_location>

using source_location = std::experimental::source_location;

void vlog(fmt::string_view format, fmt::format_args args)
{
  fmt::vprint(format, args);
}

template <typename S, typename... Args>
void log(const S& format, const source_location& location, Args&&... args)
{
  vlog(format, fmt::make_args_checked<fmt::string_view, uint32_t, Args...>(format, location.file_name(), location.line(), args...));
}

#define MY_LOG(format, ...) log(FMT_STRING("{},{}, " format), source_location::current(), __VA_ARGS__)

int main() {
  MY_LOG("invalid squishiness: {}", 42);
}

Run Code Online (Sandbox Code Playgroud)

哪个产量正确./example.cpp,20, …

c++ default-arguments variadic-templates fmt

7
推荐指数
1
解决办法
623
查看次数

有没有办法抑制用户定义的类的 fmt 范围格式化程序?

我有一个简单的类,它有一个 tostring() 方法:

class MyClass {
  public:

    std::string tostring() const;

    static iterator begin();
    static iterator end();
};
Run Code Online (Sandbox Code Playgroud)

虽然我现在正在使用 fmt 库,但这段代码是从没有的代码中移植过来的,所以许多遗留类都实现了 tostring() 方法,而且我有一个模板可以为任何类生成 fmt::formatter有那个方法 它一直运行良好。

然而,这个特殊的类也有开始/结束功能。但是,它们是静态的(此类类似于枚举,您可以遍历所有可能的值),并且与格式无关。

一切都很好,直到我需要为一些不同的代码包含 fmt/ranges.h。问题是有一个范围格式化程序可以看到开始/结束函数并希望将类格式化为范围。现在,如果我尝试格式化类,我会得到格式化程序的一个模棱两可的实例(一个用于我要使用的模板,一个用于范围格式化程序)。

有没有办法让范围格式化程序忽略这个类?

一个完整的例子是:

#include <type_traits>
#include <utility>
#include <string>
#include <vector>
#include <fmt/format.h>
// #include <fmt/ranges.h>


// Create formatter for any class that has a tostring() method

template <typename T>
struct has_tostring_member {
private:
  template <typename U>
  static std::true_type  test( decltype(&U::tostring) );
  template <typename U>
  static std::false_type test(...);
public:
  using result = decltype(test<T>(0) ); …
Run Code Online (Sandbox Code Playgroud)

c++ fmt

7
推荐指数
1
解决办法
97
查看次数

将 std::format 与具有运算符 &lt;&lt; 的类型一起使用

使用fmt库,您可以轻松格式化已定义的类型operator<<。正如这里所解释的,您可以ostream_formatter使用一行代码进行扩展:

template <> struct fmt::formatter<Foo> : ostream_formatter {};
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

fmt::format("Foo is {}", Foo());
Run Code Online (Sandbox Code Playgroud)

类似的事情可能吗std::format()?我有已经定义的类型operator<<,所以我想开始将它们与std::format().

如果我尝试编写自己的格式化程序,我不知道如何ostream从成员函数中的参数中获取 an format()

template <> struct fmt::formatter<Foo> : ostream_formatter {};
Run Code Online (Sandbox Code Playgroud)

直接编写格式化程序而不依赖于 是否更好operator<<

c++ c++20 fmt

7
推荐指数
1
解决办法
835
查看次数