在Boost.Spirit.Qi使用错误雪崩
-
19-09-2019 - |
题
我不能够找出什么是错我的代码。 Boost的模板让我发疯!我不能作出正面或反面了这一切,所以我不得不问。
这有什么错呢?
#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/spirit/include/qi.hpp>
void parsePathTest(const std::string &path)
{
namespace lambda = boost::lambda;
using namespace boost::spirit;
const std::string permitted = "._\\-#@a-zA-Z0-9";
const std::string physicalPermitted = permitted + "/\\\\";
const std::string archivedPermitted = permitted + ":{}";
std::string physical,archived;
// avoids non-const reference to rvalue
std::string::const_iterator begin = path.begin(),end = path.end();
// splits a string like "some/nice-path/while_checking:permitted#symbols.bin"
// as physical = "some/nice-path/while_checking"
// and archived = "permitted#symbols.bin" (if this portion exists)
// I could barely find out the type for this expression
auto expr
= ( +char_(physicalPermitted) ) [lambda::var(physical) = lambda::_1]
>> -(
':'
>> (
+char_(archivedPermitted) [lambda::var(archived) = lambda::_1]
)
)
;
// the error occurs in a template instantiated from here
qi::parse(begin,end,expr);
std::cout << physical << '\n' << archived << '\n';
}
错误的数量是巨大的;我建议谁愿意帮助在编制该人他们的(相信我,这里粘贴是不现实)。我使用最新的TDM-GCC版本(GCC 4.4.1)和Boost版本1.39.00。
作为奖励,我想问一下其他两件事情:C ++ 0x中的新功能static_assert
是否有助于加速在这个意义上,以及是否我上面引述的实施是一个好主意,或者我应该使用Boost的字符串算法库。就后者可能给一个更好的表现呢?
感谢。
- 修改
下面的非常小的样品失败起初具有完全相同的误差与上述代码。
#include <iostream>
#include <boost/spirit/include/qi.hpp>
int main()
{
using namespace boost::spirit;
std::string str = "sample";
std::string::const_iterator begin(str.begin()), end(str.end());
auto expr
= ( +char_("a-zA-Z") )
;
// the error occurs in a template instantiated from here
if (qi::parse(begin,end,expr))
{
std::cout << "[+] Parsed!\n";
}
else
{
std::cout << "[-] Parsing failed.\n";
}
return 0;
}
- 编辑2
我仍然不知道它为什么没有在我的旧版本提升(1.39)的工作,但升级到升压1.42解决了这个问题。下面的代码编译,并用升压1.42完美运行:
#include <iostream>
#include <boost/spirit/include/qi.hpp>
int main()
{
using namespace boost::spirit;
std::string str = "sample";
std::string::const_iterator begin(str.begin()), end(str.end());
auto expr
= ( +qi::char_("a-zA-Z") ) // notice this line; char_ is not part of
// boost::spirit anymore (or maybe I didn't
// include the right headers, but, regardless,
// khaiser said I should use qi::char_, so here
// it goes)
;
// the error occurs in a template instantiated from here
if (qi::parse(begin,end,expr))
{
std::cout << "[+] Parsed!\n";
}
else
{
std::cout << "[-] Parsing failed.\n";
}
return 0;
}
感谢您的提示,hkaiser。
解决方案
的几点意见:一)不使用与加速V1.39和V1.40分布式灵V2 beta版。至少使用精神V2.1(如升压V1.41发布),而不是,因为它包含的很多的bug修复和性能增强(包括,编译时和运行时的性能)。如果不能切换加速版本,只读的这里如何进行。 B)尽量避免使用boost ::拉姆达或升压::绑定精神V2.x.是的,我知道,文档说它的工作原理,但你要知道自己在做什么。使用boost ::凤凰表达式来代替。精神“知道”关于凤凰,这使得编写语义动作更容易。如果您使用的凤凰,你的代码如下:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
std::string physical, archived;
auto expr
= ( +char_(physicalPermitted) ) [phoenix::ref(physical) = qi::_1]
>> -(
':'
>> ( +char_(archivedPermitted) )[phoenix::ref(archived) = qi::_1]
)
;
但是,如果你使用圣灵的内置属性传播规则,你的整体解析器将得到更简单:
std::string physical;
boost::optional<std::string> archived;
qi::parse(begin, end,
+qi::char_(physicalPermitted) >> -(':' >> +qi::char_(archivedPermitted)),
physical, archived);
即。没有必要有在所有语义动作。如果您需要了解属性处理的详细信息,请参阅精神网站关于属性的魔法系列文章。
编辑:
关于你static_assert问题:是static_assert,能改善错误信息,因为它可以用来尽早触发编译器错误。事实上,灵使用这种技术已经广泛。但它无法保护用户在所有的情况下得到这些巨大的错误消息,但只对那些用户错误的程序员没想到。只有概念(不幸的是没有使之进入新的C ++标准)可能已被用于通常降低的错误消息TEH大小。
关于你Boost的字符串算法问题:当然有可能利用这个库进行简单的任务,你的。你甚至可能会更好使用Boost.Tokenizer(如果你需要的是分割的输入字符串“:”)。精神的表现应该是相当的字符串算法的相应表现,而这当然取决于你写的代码。如果假定利用串算法将需要一个传过来的输入字符串数据,则精神不会更快(因为它是一个做通以及)。
无论是升压字符串算法也不升压标记生成器可以给你匹配的字符的验证。你的灵语法只有你在字符类指定的字符匹配。所以,如果你需要这种匹配/验证,您应该使用酒精或升压正则表达式。