La bibliothèque Phoenix est antérieure à noexcept.
Depuis c++17 La spécification noexcept fait partie du type de fonction et peut figurer dans n'importe quel déclarateur de fonction. .
L'implication est que vous rencontrez les limitations de Phoenix lorsque vous utilisez les spécifications noexcept en mode c++17.
Plus précisément, c'est la déduction du type de retour qui semble ne pas fonctionner : Les fonctions qui ne diffèrent que par leur spécification d'exception ne peuvent pas être surchargées (tout comme le type de retour, la spécification d'exception fait partie du type de fonction, mais pas de la signature de la fonction) (depuis C++17).
Améliorations
Dans votre cas, puisque vous utilisez C++17, pourquoi ne pas simplifier l'ensemble ? En direct sur Coliru
qi::rule<std::string::const_iterator, Duration()> durationRule //
= qi::eps[_val = 0s] //
>> (qi::int_ >> "h")[_val += _1 * 1h];
La sortie
"2m" -> failed
"3h" -> 10800
"4s" -> failed
donne mon intention !
Bonus Extension 1 : unités
En utilisant un tableau simple comme
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)
;
Maintenant, avec le changement trivial de
>> +(qi::int_ >> unit_)[_val += _1 * _2];
Il évalue un grand nombre de séquences intéressantes : En direct sur 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";
}
}
Impressions
"2m" -> 120s
"3h" -> 10800s
"4s" -> 4s
"1ms -1ns" -> 0.000999999s
"1 day -23h" -> 3600s
"3600000000ns" -> 3.6s
"1 day -23h -50m +3600000000ns" -> 603.6s
Notez que j'ai modifié certains détails pour que cela fonctionne. Notamment qi::eoi
pour vérifier que toute l'entrée est consommée, et en déclarant le skipper dans la règle ( blank
au lieu de space
pour exclure les nouvelles lignes). Sans cela, la règle était implicitement un lexème ( Questions relatives au skipper de l'esprit Boost )