gpt4 book ai didi

C++ 与 D 的示例。前端程序RPN计算器来自D主页对比

转载 作者:搜寻专家 更新时间:2023-10-31 02:19:59 24 4
gpt4 key购买 nike

在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));
}
}

我有一些问题:

  1. 有没有办法扩展内联代码并将其与环境混合,或者在不使用宏的情况下扩展像 D 中那样的优化开关?在 D 中有一个 foreach 可以扩展案例的代码内联。

  2. 有没有办法借助字符串的 constexpr 来模拟 switch?

  3. 我使用带有模板参数的外部函数,因为看起来lambdas 不能指定模板参数,所以我必须使用一个冗长的函数对象来捕获堆栈加上模板化的 operator()()。有没有办法解决这个问题并保持主要的功能过程和binop?

我认为 D 版本在元编程领域得分很高,但想知道如何在 C++ 中做到最好。

最佳答案

如果目标是干净的代码和/或尽可能多地使用语言功能,那么尝试将语言 1 的某些代码直接翻译成语言 2 很少是最佳解决方案。在忽略 D 实现的同时重写你的 RPN 计算器可能会更好......好吧,你的问题:

1)
Tldr:不直接。
switch 的扩展 case 构造在它的原始语法中,没有宏,只是不存在。(像 eval 这样的东西并不存在,C++ 是一种“硬编译”语言,没有任何类型的解释器,程序中也没有嵌入式编译器。)
但是既然这里的一切都是基于仿函数/lambdas,为什么不制作一个映射(std::map 或其他任何东西)来将符号映射到函数,然后只调用符号的函数而不使用 切换吗?

2)
是的,这是可能的。
switch 单独只适用于整数,但正如你自己所说,一个 constexpr 函数接受一个字符串并返回一个 int,不同的字符串被映射到不同的 int(希望如此),可以使用。
这些案例看起来像

case myhashfunction("stringvalue"):  
...
constexpr unsigned long myhashfunction(const char *) {...}

或者,使用用户定义的文字,例如。

case "stringvalue"_hash:

有人实际实现了 CRC32:https://stackoverflow.com/a/9842857/3134621

3)
Tldr:如果它应该在函数内部,则不。
虽然 lambda 中的 auto 关键字具有一些类似模板的功能,但它不如全功能模板强大(例如,没有文字,不强制多个参数使用相同的类型 等.).
在没有 lambda 语法快捷方式的情况下,在函数中创建仿函数类也是不可能的:函数中的类定义不能使用模板。
因此,您需要在将使用 lambda/仿函数的函数之外添加一些东西。

关于C++ 与 D 的示例。前端程序RPN计算器来自D主页对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33229762/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com