切换到更高的 Boost 版本 1.6.1 时出现编译错误
Compilation error by switching to higher Boost Version 1.6.1
我将 Boost 版本从 1.6.1 切换到>=1.6.2,我的 boost::spirit
解析器代码无法编译。实际上,我认为问题与从1.6.1版本到1.6.2版本的Boost变体中的错误修复有关。
版本 1.6.2 的发行说明说:
Variant constructors and assignment operators now do not participate in overload resolutions if variant can not hold the input type #5871, #11602
这是我失败代码的剥离版本:
Parser.h
#pragma once
#include <string>
#include <boost/variant.hpp>
struct AccTag {};
template <typename tag> struct unop;
typedef unop<AccTag> Acc;
typedef boost::variant<
boost::recursive_wrapper<Acc>
> computationExpr;
typedef boost::variant<
boost::recursive_wrapper<computationExpr>,
int
> expr;
template <typename tag> struct unop
{
unop() : oper1() {
}
explicit unop(const expr& o) : oper1(o) { }
expr oper1;
};
expr parse(const std::string& expression, bool& ok);
解析器.cpp
#include "Parser.h"
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
using namespace boost;
template <typename Iterator = std::string::iterator, typename Skipper = spirit::qi::space_type>
class ParserImpl : public spirit::qi::grammar<Iterator, expr(), Skipper>
{
public:
ParserImpl() : ParserImpl::base_type(expr_)
{
using namespace boost::spirit::qi;
using namespace boost::phoenix;
expr_ = props_.alias();
props_ = (
(lit("Acc") >> "(" >> int_ >> ")")[_val = construct<Acc>(_1) /* Most likely the source of the error */]
);
}
spirit::qi::rule<Iterator, expr(), Skipper> props_;
spirit::qi::rule<Iterator, expr(), Skipper> expr_;
};
expr parse(const std::string& expression, bool& ok)
{
expr result;
std::string formula = expression;
ParserImpl<> parser;
auto b = formula.begin();
auto e = formula.end();
ok = spirit::qi::phrase_parse(b, e, parser, spirit::qi::space, result);
if (b != e) {
ok = false;
}
return result;
}
代码在 1.6.1 版中编译没有问题,但在 1.6.2 版中失败,并显示错误:
.../proto/transform/default.hpp(154): error C2679: Binary operator "=": ...
我想在 1.6.1 版中有一个从 computationExpr
到 expr
的隐式转换,这不再被允许。
如何修复此代码?我认为_val = construct<Acc>(_1)
中的某些东西必须改变,但我缺乏做到这一点的技能。
事实上,自 1.62 以来,recursive_wrapper更多地限制了隐式构造的选项:
魔杖盒在提升 1.61
boost::variant<int, boost::recursive_wrapper<std::string> > x;
x = "worked before";
std::cout << boost::get<std::string>(x) << "n";
在提升 1.62 上损坏
boost::variant<int, boost::recursive_wrapper<std::string> > x;
x = "worked before";
std::cout << boost::get<std::string>(x) << "n";
在这种情况下,很容易修复:在 Boost 1.62 上修复
x = std::string("Hello world");
您的代码
在您的代码中,递归包装器的嵌套使用使事情复杂化。好消息是,你不需要有两层。只需掉一个:
typedef boost::variant<
int,
computationExpr
> expr;
实例化已经被第二个递归包装器充分解耦。现在,一切又好了。
演示时间
请注意一些样式修复/建议:
此外,我对
expr
变体中的元素进行了重新排序,因为它们在默认构造上触发了无限递归。
住在科里鲁
#pragma once
#include <string>
#include <boost/variant.hpp>
struct AccTag {};
template <typename> struct unop;
typedef unop<AccTag> Acc;
typedef boost::variant<
boost::recursive_wrapper<Acc>
> computationExpr;
typedef boost::variant<
int,
computationExpr
> expr;
template <typename> struct unop {
unop() : oper1() { }
explicit unop(const expr& o) : oper1(o) { }
expr oper1;
};
expr parse(const std::string& expression, bool& ok);
#include "Parser.h"
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
namespace qi = boost::spirit::qi;
template <typename Iterator = std::string::const_iterator, typename Skipper = qi::space_type>
class ParserImpl : public qi::grammar<Iterator, expr(), Skipper>
{
public:
ParserImpl() : ParserImpl::base_type(expr_)
{
namespace phx = boost::phoenix;
using namespace qi;
expr_ = props_.alias();
props_ =
(lit("Acc") >> '(' >> int_ >> ')')[_val = phx::construct<Acc>(_1)]
;
}
private:
qi::rule<Iterator, expr(), Skipper> props_;
qi::rule<Iterator, expr(), Skipper> expr_;
};
expr parse(const std::string& formula, bool& ok)
{
expr result;
ParserImpl<> parser;
auto b = formula.begin();
auto e = formula.end();
ok = qi::phrase_parse(b, e, parser >> qi::eoi, qi::space, result);
return result;
}
static inline std::ostream& operator<<(std::ostream& os, Acc const& o) {
return os << "Acc(" << o.oper1 << ")";
}
int main() {
bool ok;
auto e = parse("Acc (3)", ok);
if (ok)
std::cout << "Parsed: " << e << "n";
else
std::cout << "Parse failedn";
}
指纹
Parsed: Acc(3)
- 用MacOS Mojave编译C++:致命错误:mpi.h:没有这样的文件或目录
- std::is_base_of表示ctor编译错误
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- Qt5:使用QCommandLineParser类时出现奇怪的编译错误
- Qt Cmake 错误编译"GuiSupportQt not found"
- Opengl 精度转换错误编译错误 E0415
- 库将ARM架构错误编译为架构X64
- RT 音频 Mac 错误 g++ 编译错误
- 错误编译Boost.log
- 错误编译QT创建者 / QT窗口小部件示例
- 错误编译MIPS32
- Visual Studio 2013 中的错误(编译和运行代码)
- 链接错误编译qt项目在visual 2010
- 无法用模板错误编译nsgmls
- 奇怪的错误.编译失败
- 如果有人调用c++中的方法,则强制错误(编译时)
- 来自autoconf测试的错误编译命令
- 时间限制超出错误C++编译
- SFML 2.3 和 CodeBlocks 错误编译