The following code is a slightly modified Proto calc2 example. Instead
of doubles I use variant, and the expression is just _1 =
_2.
This code triggers assertion in variant/detail/forced_return.hpp, so
it looks like some variant instance gets messed up. It happens when
the value returned from proto::eval(*this, ctx) is being copied.
It can be reproduced both with MSVC and gcc, with Boost 1.60.
Is there any workaround for this issue?
Thanks.
//////////////
#include <iostream>
#include
#include
#include
#include
namespace proto = boost::proto;
using proto::_;
typedef boost::variant var_t;
template<typename Expr>
struct calculator_expression;
// Tell proto how to generate expressions in the calculator_domain
struct calculator_domain
: proto::domain >
{};
// Will be used to define the placeholders _1 and _2
template<int I> struct placeholder {};
// Define a calculator context, for evaluating arithmetic expressions
// (This is as before, in calc1.cpp)
struct calculator_context
: proto::callable_context< calculator_context const >
{
// The values bound to the placeholders
var_t d[2];
// The result of evaluating arithmetic expressions
typedef var_t result_type;
explicit calculator_context(const var_t &d1 = var_t(), const var_t
&d2 = var_t())
{
d[0] = d1;
d[1] = d2;
}
// Handle the evaluation of the placeholder terminals
template<int I>
result_type operator ()(proto::tag::terminal, placeholder<I>) const
{
return d[ I - 1 ];
}
};
// Wrap all calculator expressions in this type, which defines
// operator () to evaluate the expression.
template<typename Expr>
struct calculator_expression
: proto::extends
{
explicit calculator_expression(Expr const &expr = Expr())
: calculator_expression::proto_extends(expr)
{}
BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
// Override operator () to evaluate the expression
var_t operator ()() const
{
calculator_context const ctx;
return proto::eval(*this, ctx);
}
var_t operator ()(const var_t &d1) const
{
calculator_context const ctx(d1);
return proto::eval(*this, ctx);
}
var_t operator ()(const var_t &d1, const var_t &d2) const
{
calculator_context const ctx(d1, d2);
return proto::eval(*this, ctx);
}
};
// Define some placeholders (notice they're wrapped in calculator_expression<>)
calculator_expression >::type> const _1;
calculator_expression >::type> const _2;
// Now, our arithmetic expressions are immediately executable function objects:
int main()
{
BOOST_PROTO_AUTO(expr, _1 = _2);
var_t a1(1), a2(2.5);
expr(a1, a2);
return 0;
}