[proto][variant] variant crashes proto expression
The following code is a slightly modified Proto calc2 example. Instead of doubles I use variant<int, double>, 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 <boost/proto/proto_typeof.hpp> #include <boost/proto/core.hpp> #include <boost/proto/context.hpp> #include <boost/variant.hpp> namespace proto = boost::proto; using proto::_; typedef boost::variant<int, double> var_t; template<typename Expr> struct calculator_expression; // Tell proto how to generate expressions in the calculator_domain struct calculator_domain : proto::domain<proto::generator<calculator_expression> > {}; // 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<Expr, calculator_expression<Expr>, calculator_domain> { 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<proto::terminal< placeholder< 1 > >::type> const _1; calculator_expression<proto::terminal< placeholder< 2 > >::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; }
On 12-05-16 21:10, Igor R wrote:
The following code is a slightly modified Proto calc2 example. Instead of doubles I use variant<int, double>, 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?
I can only reproduce it with Clang. GCC 4.9+ is fine Are you using libc++?
Is there any workaround for this issue?
I can only reproduce it with Clang. GCC 4.9+ is fine Are you using libc++?
Well, I didn't try it with clang/libc++ prior to posting it here, but it looks like it fails with any possible compiler (http://melpon.org/wandbox).
participants (3)
-
Igor R
-
Igor R.
-
Seth