我可以将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; }
};
我很欣赏这个例子有一些粗糙的边缘,但我想知道是否有任何尝试沿着这些线路?
答案 0 :(得分:3)
使用您可以找到here作为“灵感”的转化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;
}
答案 1 :(得分:-2)
字符串化是一种预处理器功能 - 您只能对预处理器可用的标记进行字符串化。类型处理(包括类型和表达式扩展)由编译器完成,该编译器在预处理器之后运行,因此您无法执行所需的字符串化。