使用 {fmt} 格式化容器

auz*_*uzn 5 c++ c++17 fmt

我正在尝试使用 {fmt} 打印 std::vector 或 std::array ,如下所示:

std::vector<double> vec = {1., 2., 3.};
fmt::print("{:0.3f}\n", fmt::join(vec, ","));
Run Code Online (Sandbox Code Playgroud)

问题是,我希望打印一个变换后的向量:

std::vector<double> vec = {1., 2., 3.};
std::vector<double> vec_dup;
std::transform(vec.begin(), vec.end(), std::back_inserter(vec_dup), [](auto x){return x * M_PI;});
fmt::print("{:0.3f}\n", fmt::join(vec_dup, ","));
Run Code Online (Sandbox Code Playgroud)

有没有办法在 C++17 中执行此操作而不需要创建新容器?

vvv*_*444 3

让我们首先看看在 C++20 中如何使用标准<ranges>库(Godbolt)轻松实现:

    std::vector<double> vec = {1., 2., 3.};

    auto func = [](auto x){ return x * M_PI; };
    auto&& new_range = vec | std::views::transform(func);
    
    fmt::print("{:0.3f}\n", fmt::join(new_range, ","));
Run Code Online (Sandbox Code Playgroud)

如果您仅限于 C++17,您有两个选择:

  1. 使用第 3 方range-v3库实现相同的功能。为此,只需替换上面的代码:

    #include <range>       --> <range/v3/view/transform.hpp>
    std::views::transform  --> ranges::views::transform
    
    Run Code Online (Sandbox Code Playgroud)

    Godbolt展示了这一点。

  2. 自己实现这样一个生成器类。该类应该获取源范围和生成器函数作为参数,实现begin()end()返回辅助迭代器类的函数。辅助迭代器类应该将迭代器保持在底层范围,并在取消引用时调用生成器函数。