简体   繁体   English

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

[英]std::format of user-defined types?

In C++20 - how do you make a user-defined type compatible with std::format ?在 C++20 中 - 如何使用户定义的类型与std::format兼容?

For example, let's say I have a type called Point :例如,假设我有一个名为Point的类型:

struct Point {
    int x;
    int y;
};

with its operator<< defined:operator<<定义:

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

then will the following program output Hello [3, 4]!那么下面的程序会输出Hello [3, 4]! ? ?

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

If yes - why and how?如果是 - 为什么以及如何?

If no - what do I have to add to the definition of Point to to make it work?如果不是 - 我必须在Point to 的定义中添加什么才能使其工作?

std::format doesn't support operator<< , you need to provide a formatter specialization for your type ( Point ) instead. std::format不支持operator<< ,您需要为您的类型( Point )提供formatter专业化。 The easiest way to do it is by reusing one of existing formatters, eg std::formatter<std::string> :最简单的方法是重用现有的格式化程序之一,例如std::formatter<std::string>

template <>
struct std::formatter<Point> : std::formatter<std::string> {
  auto format(Point p, format_context& ctx) {
    return formatter<string>::format(
      std::format("[{}, {}]", p.x, p.y), ctx);
  }
};

This will give you all format specifications supported by std::string out of the box.这将为您提供开箱即用的std::string支持的所有格式规范。 Here is an example of formatting Point with center alignment padded with '~' to 10 characters:下面是一个使用“~”填充中心对齐到 10 个字符的格式化Point示例:

auto s = std::format("{:~^10}", Point{1, 2});
// s == "~~[1, 2]~~"

which is nontrivial to achieve with iostreams.使用 iostreams 实现这一点非常重要。

You have to specialize std::formatter for your type.您必须为您的类型专门化std::formatter

namespace std
{
    template<class CharT>
    struct formatter<Point, CharT>
    {  
        template <typename FormatParseContext>
        auto parse(FormatParseContext& pc)
        {
            // parse formatter args like padding, precision if you support it
            return pc.end(); // returns the iterator to the last parsed character in the format string, in this case we just swallow everything
        }

        template<typename FormatContext>
        auto format(Point p, FormatContext& fc) 
        {
            return std::format_to(fc.out(), "[{}, {}]", p.x, p.y);
        }
    };
}

I don't think the ostream operator will work but I have no sources to support this claim.我不认为 ostream 操作符会起作用,但我没有支持这种说法的来源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM