在D网站上,当您进入网站时,前端会显示一个RPN计算器示例。 由于D是我强大的元编程的参考(除了Lisp), 我想知道如何将一段代码从C ++转换为D.代码片段不需要相同,但应该是相似的。我放弃了使用宏:
部分D版本:
Array!int stack;
void binop(string op)()
{
stack[$ - 2] = mixin("stack[$ - 2] " ~
op ~ " stack[$ - 1]");
stack.removeBack();
writeln(stack[$ - 1]);
}
void process(in char[] token)
{
alias Ops = AliasSeq!("+", "-", "*", "/", "%");
Lswitch:
switch (token)
{
foreach (op; Ops)
{
case op:
binop!op();
break Lswitch;
}
case "=":
writeln(stack[$ - 1]);
stack.removeBack();
break;
default:
stack.insertBack(token.to!int);
break;
}
}
部分C ++版本在某些实用程序的帮助下:
template <char Op>
void binop(std::vector<int> & s) {
//Returns std::minus<>, std::plus<>, etc.
using Op_t = opstr_to_func_object_t<Op>;
s[s.size() - 2] = Op_t{}(s[s.size() - 2], s[s.size() - 1]);
s.pop_back();
std::cout << s[s.size() - 1] << '\n';
}
template <char Op>
constexpr char op_name<Op> = std::integral_constant<char, Op>;
void process (std::string const & token, vector<int> & s) {
using namespace std;
constexpr auto ops = make_tuple(op_name<'+'>,
op_name<'-'>,
op_name<'*'>,
op_name<'/'>,
op_name<'%'>);
Lswitch:
switch (token[0]) {
//Cannot expand cases inline
// foreach([&](auto && elem) {
// constexpr auto op_str = decltype(elem)::value
//
// }, Ops{});
case "=":
std::cout << s[s.size() - 1] << '\n';
s.pop_back();
break;
default:
s.push_back(stoi(token));
}
}
我有一些问题:
有没有办法扩展内联代码并将其与环境或内容混合使用 在不使用宏的情况下扩展D中的优化开关?在D中,有一个foreach可以扩展内联代码。
有没有办法在constexpr的帮助下为字符串模拟开关?
我使用外部函数和模板参数,因为它似乎 lambdas不能指定模板参数,所以我必须使用一个详细的函数对象来捕获堆栈和模板化的operator()()。有没有办法解决这个并保持 主要的功能进程和binop?
我认为D版在元编程领域得分很高, 但是想知道如何在C ++中做到最好。
答案 0 :(得分:2)
如果目标是干净的代码和/或尽可能多地使用语言功能,尝试将语言1的某些代码直接翻译为语言2很少是最佳解决方案。重写你的RPN计算器而忽略D实现可能会更好......好吧,你的问题:
<强> 1)强>
Tldr:不是直接的。
eval
的扩展案例构造在其原始语法中没有宏,只是不存在。
(而std::map
之类的东西并不存在,C ++是一种&#34;硬编译的语言,没有任何解释器,程序中没有嵌入式编译器。)
但由于这里的所有内容都基于仿函数/ lambdas,为什么不制作一个映射(switch
或其他任何东西)来将符号映射到函数,然后只调用符号函数而不使用switch
?
<强> 2)强>
是的,这是可能的。
仅constexpr
仅适用于整数,但正如您所说,可以使用case myhashfunction("stringvalue"):
...
constexpr unsigned long myhashfunction(const char *) {...}
函数获取字符串并返回一个int,其中不同的字符串将映射到不同的int(希望如此)。 />
案件看起来像
case "stringvalue"_hash:
或者,用户定义的文字,例如
auto
有人实际实施了CRC32:https://stackoverflow.com/a/9842857/3134621
第3)强>
Tldr:如果它应该在函数内部,没有。
虽然lambdas中的{{1}}关键字具有一些类似模板的功能,但它没有全功能模板那么强大(例如,没有文字,没有强制多个参数的相同类型等等)。
在函数中创建一个没有lambda语法快捷方式的仿函数类也是不可能的:函数中的类定义可能不使用模板。
因此,您将需要使用lambda / functor的函数之外的东西。