我正在尝试为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_[...]
部分,那么它可以正常工作。
我怎样才能让它发挥作用?
答案 0 :(得分: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