我可以将Boost Phoenix表达式字符串化吗?

时间:2013-03-27 22:05:58

标签: c++ templates boost boost-phoenix boost-proto

我可以将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; }
};

我很欣赏这个例子有一些粗糙的边缘,但我想知道是否有任何尝试沿着这些线路?

2 个答案:

答案 0 :(得分:3)

使用您可以找到here作为“灵感”的转化eval

Live example

#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;
}

答案 1 :(得分:-2)

字符串化是一种预处理器功能 - 您只能对预处理器可用的标记进行字符串化。类型处理(包括类型和表达式扩展)由编译器完成,该编译器在预处理器之后运行,因此您无法执行所需的字符串化。