【问题标题】:Using Boost Karma to print boost::posix_time::time_duration使用 Boost Karma 打印 boost::posix_time::time_duration
【发布时间】:2018-02-06 20:49:40
【问题描述】:

我正在尝试为boost::posix_time::duration 编写一个简单的生成器,以便在另一个生成器中使用。我现在的症结是我想要打印的“+”或“-”。到目前为止我所拥有的是:

struct GetSign
{
    template<typename> struct result { typedef char type; };

    template<typename TimeDur>
    const char operator()(const TimeDur& dur) const
    {
        return dur.is_negative() ? '-' : '+';
    }
};

boost::phoenix::function<GetSign>   phx_getsign;

struct TimeDurationGenerator
    : boost::spirit::karma::grammar<boost::spirit::ostream_iterator, boost::posix_time::time_duration()>
{
    TimeDurationGenerator()
        : TimeDurationGenerator::base_type(start_)
    {
        namespace bsk = boost::spirit::karma;
        namespace bpt = boost::posix_time;

        start_
            = sign_[bsk::_1 = phx_getsign(bsk::_val)]
            << bsk::right_align(2,'0')[bsk::int_[bsk::_1 = boost::phoenix::bind(&bpt::time_duration::hours, bsk::_val)]]
            << ':'
            << bsk::right_align(2,'0')[bsk::int_[bsk::_1 = boost::phoenix::bind(&bpt::time_duration::minutes,bsk::_val)]];
    }

    boost::spirit::karma::rule<boost::spirit::ostream_iterator, char()> sign_;
    boost::spirit::karma::rule<boost::spirit::ostream_iterator, boost::posix_time::time_duration()> start_;
};

虽然这确实编译(至少在 clang 上)但它不起作用,因为没有输出。当我将此生成器包含在另一个生成器中时,输出总是在到达此处时停止。如果我删除规则的 sign_[...] 部分,那么它就可以工作。

我怎样才能让它工作?

【问题讨论】:

    标签: c++ boost boost-spirit


    【解决方案1】:

    您从未定义过sign_。事实上,你不需要它:

            char_[_1 = phx_getsign(_val)]
    

    但我会避免将方形钉子强行插入圆孔中。如果您需要这种级别的控制,请制作一个原始生成器来完成它。事实上,IO 流操纵器已经涵盖了:

    Live On Coliru

    #include <boost/date_time/posix_time/posix_time.hpp>
    #include <boost/spirit/include/karma.hpp>
    #include <iomanip>
    namespace bsk = boost::spirit::karma;
    namespace bpt = boost::posix_time;
    
    template <typename It = boost::spirit::ostream_iterator>
    struct TimeDurationGenerator : bsk::grammar<It, bpt::time_duration()>
    {
        TimeDurationGenerator() : TimeDurationGenerator::base_type(start_) {
            duration_ = bsk::stream;
            start_    = duration_;
        }
      private:
        struct wrap {
            bpt::time_duration d;
            wrap(bpt::time_duration const& d) : d(d) {}
            friend std::ostream& operator<<(std::ostream& os, wrap const& w) {
                return os << std::setfill('0') << std::internal
                    << std::setw(3) << std::showpos   << w.d.hours() << ":"
                    << std::setw(2) << std::noshowpos << std::abs(w.d.minutes());
            }
        };
        bsk::rule<It, bpt::time_duration()> start_;
        bsk::rule<It, wrap()> duration_;
    };
    
    int main() {
        for (auto str : { "-7:30", "7", "323:87:13" }) {
            std::cout << format(TimeDurationGenerator<>{}, bpt::duration_from_string(str)) << "\n";
        }
    }
    

    打印

    -07:30
    +07:00
    +324:27
    

    【讨论】:

    • 谢谢!关于您对我的其他一个问题的评论,我一定会牢记这一点,接下来我会发布一个问题。
    • @sehe,与主题无关,但在全局命名空间中声明了 karma format() 吗?
    • @sehe,谢谢!我从你们的许多 cmets 那里得到了一些新的东西。
    猜你喜欢
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多