Могу ли я привести в порядок выражение Boost Phoenix?

Могу ли я преобразовать выражение Boost Phoenix в репрезентативную строку C ++? Я мог бы иметь:

stringify(_1<_2);

который может затем создать строку, содержащую что-то вроде:

template <class T1, class T2>
struct foo {
auto operator()(T1 x1, T2 x2)
-> decltype(x1 < x2)
{ return    x1 < x2; }
};

Я ценю, что у этого примера есть некоторые грубые края, но мне интересно, предпринимались ли какие-либо действия в этом направлении?

5

Решение

Использование преобразования eval что вы можете найти Вот как «вдохновение».

Живой пример.

#include <iostream>
#include <string>
#include <sstream>

#include <boost/phoenix.hpp>
#include <boost/phoenix/core/arity.hpp>
#include <boost/lexical_cast.hpp>

namespace phx=boost::phoenix;
namespace proto=boost::proto;

struct do_print : proto::callable
{
typedef std::string result_type;

template <typename NotArgument>
std::string operator()(NotArgument n)
{
return boost::lexical_cast<std::string>(n);
}

template <int I>
std::string operator()(phx::argument<I>)
{
return std::string("x")+boost::lexical_cast<std::string>(I-1);
}

#define UNARY_OP(TAG, OP)                                                       \
template<typename Arg>                                                      \
std::string operator()(proto::tag::TAG, Arg arg) const                           \
{                                                                           \
return std::string("(") + OP + arg + ")";                                                          \
}                                                                           \
/**/

#define BINARY_OP(TAG, OP)                                                      \
template<typename Left, typename Right>                                     \
std::string operator()(proto::tag::TAG, Left left, Right right) const            \
{                                                                           \
return std::string("(") + left + OP + right + ")";                                                   \
}                                                                           \
/**/

UNARY_OP(negate, "-")
BINARY_OP(plus, "+")
BINARY_OP(minus, "-")
BINARY_OP(multiplies, "*")
BINARY_OP(divides, "/")
BINARY_OP(less, "<")
BINARY_OP(greater, ">")
/*... others ...*/
};

struct print_expression
: proto::or_<
proto::when<proto::terminal<proto::_>, do_print(proto::_value)>
, proto::otherwise<do_print(proto::tag_of<proto::_>(), print_expression(proto::pack(proto::_))...)>
>
{};

struct do_get_arity : proto::callable
{
typedef int result_type;

template <typename NotArgument>
int operator()(NotArgument)
{
return 0;
}

template <int I>
int operator()(phx::argument<I>)
{
return I;
}template<typename Tag, typename Arg>
int operator()(Tag, Arg arg) const
{
return arg;
}
/**/

template<typename Tag, typename Left, typename Right>
int operator()(Tag, Left left, Right right) const
{
return std::max(left,right);                                                   \
}

};

struct get_arity
: proto::or_<
proto::when<proto::terminal<proto::_>, do_get_arity(proto::_value)>
, proto::otherwise<do_get_arity(proto::tag_of<proto::_>(),get_arity(proto::pack(proto::_))...)>
>
{};template <typename Expr>
std::string stringify(const Expr& expr, const std::string& name="foo")
{
std::stringstream result;
int current_arg;
int arity= get_arity()(expr);

result << "template <";

for(current_arg=0;current_arg<arity-1; ++current_arg)
result << " typename T" << current_arg << ",";
result << " typename T" << current_arg;

result << " >\n";
result << "struct " << name << " {\n\t";
result << "auto operator()(";

for(current_arg=0;current_arg<arity-1; ++current_arg)
result << " T" << current_arg << " x" << current_arg << ",";
result << " T" << current_arg << " x" << current_arg;
result << " )\n\t\t-> typename std::remove_reference< decltype( " << print_expression()(expr) << " ) >::type\n";
result << "\t{ return " << print_expression()(expr) << "; }\n";
result << "};\n";

return result.str();
}

int main()
{
using phx::placeholders::_1;
using phx::placeholders::_2;
using phx::placeholders::_3;
std::cout << stringify(-_1) << std::endl;
std::cout << stringify(_1+_2) << std::endl;
std::cout << stringify(_1+_2*_3) << std::endl;

std::cout << stringify((_1+_2)*_3) << std::endl;
std::cout << stringify(_1>2) << std::endl;
std::cout << stringify(_1*(-_2)) << std::endl;
return 0;
}
3

Другие решения

Стрификация — это функция препроцессора — вы можете преобразовать в строку только те токены, которые доступны препроцессору. Обработка типов (включая расширение типов и выражений) выполняется компилятором, который запускается после препроцессор, таким образом, вы не можете выполнить желаемую строку.

-2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector