Phoenix 库早于 noexcept。
c++17 起The noexcept-specification is a part of the function type and may appear as part of any function declarator.
言下之意就是在c++17模式下使用noexcept规范会遇到Phoenix的限制。
具体来说,似乎破坏的是返回类型推导:仅在异常规范上不同的函数不能被重载(就像返回类型一样,异常规范是函数类型的一部分,但不是函数的一部分签名)(C++17 起)。
改进
在您的情况下,既然您使用的是 C++17,为什么不简化整个事情呢? Live On Coliru
qi::rule<std::string::const_iterator, Duration()> durationRule //
= qi::eps[_val = 0s] //
>> (qi::int_ >> "h")[_val += _1 * 1h];
输出
"2m" -> failed
"3h" -> 10800
"4s" -> failed
泄露了我的意图!
额外奖励 1:单位
使用简单的表格
qi::symbols<char, Duration> unit_;
unit_.add
("ns", 1ns) ("nano", 1ns)
("us", 1us) ("μs", 1us) ("micro", 1us)
("ms", 1ms) ("milli", 1ms)
("s", 1s)
("m", 1min) ("min", 1min)
("h", 1h) ("hour", 1h)
("d", 24h) ("day", 24h)
;
现在有了细微的变化
>> +(qi::int_ >> unit_)[_val += _1 * _2];
它确实评估了大量有趣的序列:Live On Coliru
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <chrono>
#include <iomanip>
using namespace std::chrono_literals;
using Duration = std::chrono::duration<int64_t, std::nano>;
namespace qi = boost::spirit::qi;
int main()
{
using namespace qi::labels; // _val, _1 etc
qi::symbols<char, Duration> unit_;
unit_.add
("ns", 1ns) ("nano", 1ns)
("us", 1us) ("μs", 1us) ("micro", 1us)
("ms", 1ms) ("milli", 1ms)
("s", 1s)
("m", 1min) ("min", 1min)
("h", 1h) ("hour", 1h)
("d", 24h) ("day", 24h)
;
qi::int_parser<int64_t, 10> int64_;
qi::rule<std::string::const_iterator, Duration(), qi::blank_type>
durationRule //
= qi::eps[_val = 0s] //
>> +(int64_ >> unit_)[_val += _1 * _2];
for (std::string const s :
{
"2m",
"3h",
"4s",
"1ms -1ns",
"1 day -23h",
"3600000000ns",
"1 day -23h -50m +3600000000ns",
}) //
{
std::cout << std::quoted(s);
Duration d{};
if (phrase_parse( //
s.begin(), s.end(), //
durationRule >> qi::eoi, //
qi::blank, d))
std::cout << " -> " << d / 1.0s << "s\n";
else
std::cout << " -> failed\n";
}
}
打印
"2m" -> 120s
"3h" -> 10800s
"4s" -> 4s
"1ms -1ns" -> 0.000999999s
"1 day -23h" -> 3600s
"3600000000ns" -> 3.6s
"1 day -23h -50m +3600000000ns" -> 603.6s
请注意,我已经改变了一些细节以使其正常工作。值得注意的是 qi::eoi 检查整个输入是否被消耗,并在规则中声明船长(blank 而不是 space 以排除换行符)。否则,无论如何,该规则都是隐含的词位 (Boost spirit skipper issues)