C++学习笔记----Strings与String View(13)-- 格式化输出客户化类型

        对于客户化类型的格式化输出,其实就是要对std::formatter的类模板实现一下其parse()和format(),到目前为止,其实关于类啊、模板啊有及C++高级编程的东西,我们都还没有涉及,一点一点在这一篇笔记中进行解释也不现实,现在,我把例子贴在这儿,等我们把相关知识都学得差不多了,再回头去看具体的语法也不迟,其实现如下:

import std;

using namespace std;

class KeyValue
{
public:
	KeyValue(string_view key, int value) : m_key{ key }, m_value{ value } {}

	const string& getKey() const { return m_key; }
	int getValue() const { return m_value; }

private:
	string m_key;
	int m_value{ 0 };
};

template<>
class std::formatter<KeyValue>
{
public:
	constexpr auto parse(auto& context)
	{
		string keyFormat, valueFormat;
		size_t numberOfParsedColons{ 0 };
		auto iter{ begin(context) };
		for (; iter != end(context); ++iter) {
			if (*iter == '}') {
				break;
			}

			if (numberOfParsedColons == 0) { // Parsing output type
				switch (*iter) {
				case 'k': case 'K':  // {:k format specifier
					m_outputType = OutputType::KeyOnly;
					break;
				case 'v': case 'V':  // {:v format specifier
					m_outputType = OutputType::ValueOnly;
					break;
				case 'b': case 'B':  // {:b format specifier
					m_outputType = OutputType::KeyAndValue;
					break;
				case ':':
					++numberOfParsedColons;
					break;
				default:
					throw format_error{ "Invalid KeyValue format." };
				}
			}
			else if (numberOfParsedColons == 1) { // Parsing key format
				if (*iter == ':') {
					++numberOfParsedColons;
				}
				else {
					keyFormat += *iter;
				}
			}
			else if (numberOfParsedColons == 2) { // Parsing value format
				valueFormat += *iter;
			}
		}

		// Validate key format specifier.
		if (!keyFormat.empty()) {
			format_parse_context keyFormatterContext{ keyFormat };
			m_keyFormatter.parse(keyFormatterContext);
		}

		// Validate value format specifier.
		if (!valueFormat.empty()) {
			format_parse_context valueFormatterContext{ valueFormat };
			m_valueFormatter.parse(valueFormatterContext);
		}

		if (iter != end(context) && *iter != '}') {
			throw format_error{ "Invalid KeyValue format." };
		}

		return iter;
	}

	auto format(const KeyValue& kv, auto& ctx) const
	{
		switch (m_outputType) {
			using enum OutputType;

		case KeyOnly:
			ctx.advance_to(m_keyFormatter.format(kv.getKey(), ctx));
			break;
		case ValueOnly:
			ctx.advance_to(m_valueFormatter.format(kv.getValue(), ctx));
			break;
		default:
			ctx.advance_to(m_keyFormatter.format(kv.getKey(), ctx));
			ctx.advance_to(format_to(ctx.out(), " - "));
			ctx.advance_to(m_valueFormatter.format(kv.getValue(), ctx));
			break;
		}

		return ctx.out();
	}

private:
	enum class OutputType
	{
		KeyOnly,
		ValueOnly,
		KeyAndValue
	};

	OutputType m_outputType{ OutputType::KeyAndValue };
	formatter<string> m_keyFormatter;
	formatter<int> m_valueFormatter;
};


int main()
{
	const size_t len{ 34 }; // Label field length
	KeyValue kv{ "Key 1", 255 };

	println("{:>{}} {}", "Default:", len, kv);
	println("{:>{}} {:k}", "Key only:", len, kv);
	println("{:>{}} {:v}", "Value only:", len, kv);
	println("{:>{}} {:b}", "Key and value with default format:", len, kv);

	println("{:>{}} {:k:*^11}", "Key only with special format:", len, kv);
	println("{:>{}} {:v::#06X}", "Value only with special format:", len, kv);
	println("{:>{}} {::*^11:#06X}", "Key and value with special format:", len, kv);

	try {
		auto formatted{ vformat("{:cd}", make_format_args(kv)) };
		println("{}", formatted);
	}
	catch (const format_error& caught_exception) {
		println("{}", caught_exception.what());
	}
}

        简单解释一句,parse()对输入进行解析,format()对输入进行化,结果如下:

                          Default: Key 1 - 255
                         Key only: Key 1
                       Value only: 255
Key and value with default format: Key 1 - 255
     Key only with special format: ***Key 1***
   Value only with special format: 0X00FF
Key and value with special format: ***Key 1*** - 0X00FF
Invalid KeyValue format.

        到今天为止,关于string及string_view的学习就全部结束了,感觉还是干货满满的吧,从下一篇开始,我们就要开始新的征程了,愿你人在学习C++的路上勇往直前、朝气蓬勃!!!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值