zoukankan      html  css  js  c++  java
  • C++20 如何扩展format

    #include <iostream>
    #include <format>
    #include <type_traits>
    #include <string>
    
    class KeyValue
    {
    public:
        KeyValue(std::string key, int value) : m_key{ std::move(key) }, m_value{ value } { }
        auto& getKey() const { return m_key; }
        auto& getValue() const { return m_value; }
    private:
        std::string m_key;
        int m_value;
    };
    
    template <>
    class std::formatter<KeyValue>
    {
    public:
        auto parse(auto& context)
        {
            auto iter = context.begin();
            const auto end = context.end();
            if (iter == end || *iter == '}')
            {
                m_out = OutputType::KeyAndValue; // {}
                return iter;
            }
            switch (*iter)
            {
            case 'a': m_out = OutputType::Key; break; // {:a} -> key
            case 'b': m_out = OutputType::Value; break; // {:b} -> value
            case 'c': m_out = OutputType::KeyAndValue; break; // {:c} -> key and value
            default:
                throw std::format_error{ "Invalid KeyValue format specifier. " };
            }
    
            ++iter;
            if (iter != end && *iter != '}')
                throw std::format_error{ "Invalid KeyValue format specifier. " };
            return iter;
        }
        auto format(const KeyValue& kv, auto& context)
        {
            switch (m_out)
            {
                using enum OutputType;
            case Key:
                return std::format_to(context.out(), "{}", kv.getKey());
            case Value:
                return std::format_to(context.out(), "{}", kv.getValue());
            default:
                return std::format_to(context.out(), "{} - {}", kv.getKey(), kv.getValue());
            }
        }
    private:
        enum class OutputType
        {
            Key, Value, KeyAndValue
        };
        OutputType m_out{ OutputType::KeyAndValue };
    };
    
    
    struct Point { int x, y; };
    
    template <>
    class std::formatter<Point>
    {
    public:
        typename std::format_parse_context::iterator parse(std::format_parse_context& context)
        {
            auto iter = context.begin();
            for (; iter != context.end() && *iter != '}'; ++iter)
            {
                if (*iter == '#') { m_hashtag = true; }
                else throw std::format_error{ "Invalid KeyValue format specifier. " };
            }
            return iter;
        }
    
        typename std::format_context::iterator format(const Point& p, std::format_context& context)
        {
            char left = m_hashtag ? '[' : '(';
            char right = m_hashtag ? ']' : ')';
            return std::format_to(context.out(), "{}{}, {}{}", left, p.x, p.y, right);
        }
    
    private:
        bool m_hashtag = false;
    };
    
    int main()
    {
        KeyValue kv{ "Key", 0 };
        Point p{ .x = 1, .y = 1 };
        try
        {
            std::cout << std::format("{}
    ", kv);
            std::cout << std::format("{:a}
    ", kv);
            std::cout << std::format("{:b}
    ", kv);
            std::cout << std::format("{:c}
    ", kv);
            std::cout << std::format("{:ab}
    ", kv);
        }
        catch (const std::exception& e)
        {
            std::cerr << e.what() << '
    ';
        }
    
        try
        {
            std::cout << std::format("{}
    ", p);
            //std::cout << std::format("{:#}
    ", p);
            //std::cout << std::format("{:#x}
    ", p);
        }
        catch (const std::exception& e)
        {
            std::cerr << e.what() << '
    ';
        }
    
    }
  • 相关阅读:
    Linux 清理boot分区
    Linux 虚拟内存
    使用mongoskin操作MongoDB
    nodejs操作session和cookie
    nodejs接收get参数和post参数
    Tomcat--在IDEA创建Java Web项目,通过tomcat启动
    Tomcat--配置
    Mac安装Tomcat
    XML--解析
    XML--约束
  • 原文地址:https://www.cnblogs.com/MasterYan576356467/p/15502458.html
Copyright © 2011-2022 走看看