gpt4 book ai didi

mixins - 从字符串获取类——通过字符串名称调用函数

转载 作者:行者123 更新时间:2023-12-02 08:46:35 26 4
gpt4 key购买 nike

好吧,我想做的事情非常复杂,但我会尽力解释一下。

假设我们想要(在编译时)类 someClass 的所有 衍生成员。然后我们只需这样做:

const string[] methods = [__traits(derivedMembers,someClass)];

现在,我们如何从 "someClass" 获取 someClass 呢? (是的,它的字符串表示)。

<小时/>

让我再解释一下我想做的事情:

我想创建一个“中间”函数,它将函数名称作为参数(以及 params 数组),并从特定的可用静态方法列表中调用适当的函数(预定义的)类集。就像execute("someFunc",["one","two","Three"]);

这是完整的(测试)代码:

class Math {
static string noArgs(string[] s) { writeln(s); return ""; }
static string withOneArg(string[] s) { writeln(s); return ""; }
static string withTwoArgs(string[] s) { writeln(s); return ""; }
}

string cases()
{
string ret = "";

const string[] methods = [__traits(derivedMembers,Math)];

foreach (string s; methods)
{
ret ~= "case \"" ~ s ~ "\": return Math."~s~"(params);";
}

return ret;
}

string execute(string what, string[] params)
{
switch (what)
{
mixin(cases());
default: break;
}
return "";
}

上述代码的问题是它只查找Math中的方法。我怎样才能以一种优雅的 D 友好方式改变它,以便它能够通过像 [Math,String,SomethingElse] 这样的类数组 - 它不必是变量(无论如何我们在编译时都需要它)?

<小时/>

更新:

尝试了以下内容:

const string[] methods = [__traits(derivedMembers,mixin("Math")];

但它提示无法在编译时解释数学

<小时/>

更新2:

另外,尝试使用Object.factory("Math")但它仍然不起作用。 (也许我只是创建 Math 类的一个实例?)

最佳答案

让我重写一下,向您展示一些很酷的技巧:

import std.stdio;

class Math {
static string noArgs(string[] s) { writeln(s); return ""; }
static string withOneArg(string[] s) { writeln(s); return ""; }
static string withTwoArgs(string[] s) { writeln(s); return ""; }
}

class String {
static string oneArg(string[] s) { return null; }
}

string execute(string what, string[] params) {
import std.string;
auto parts = what.split(".");
auto className = parts[0];
auto methodName = parts[1];

import std.typetuple;
switch(className) {
default: assert(0, "unknown class");
foreach(possibleClass; TypeTuple!(Math, String)) {
case possibleClass.stringof:
switch(methodName) {
default: assert(0, "unknown method");
foreach(memberName; __traits(derivedMembers, possibleClass)) {
case memberName:
return __traits(getMember, possibleClass, memberName)(params);
break;
}
}
break;
}
}
assert(0);
}

void main() {
execute("Math.withOneArg", ["cool"]);
execute("String.oneArg", ["cool"]);
}

请注意,根本没有使用 mixin 表达式。我没有从字符串中获取类的实例,而是创建了我想要使用的所有类的 TypeTuple。这比 mixin 更可取,因为这样在不同范围内使用时就不太可能找到名称类;如果 possibleClasses 是从不同模块执行的编译时参数,则类列表仍然有效,而字符串列表将看到未定义的标识符错误,因为库模块不会导入您的用户模块。

我删除的另一个 mixin 是生成案例的。这看起来很疯狂,但在 D: 中是允许的:如果你有一个编译时 foreach (即,在某种内置元组上的 foreach ,例如 TypeTuple、模板参数列表、__traits 的结果...)您实际上可以将 case 语句放入其中!

因此,您所要做的就是在要比较的运行时变量上编写一个常规的 switch 语句,将 foreach 放入其中循环编译-时间你正在寻找的东西,case that_loop_var:然后繁荣,你在做生意。

同样,我使用 __traits(getMember) 而不是 mixin 字符串来调用该方法。这个解决方案将有助于避免名称冲突,并且 IMO 是更干净的代码。如果需要的话,它还可以处理重载(使用 __traits(getOverloads) 而不是 __traits(getMember),您可以循环遍历每个重载并匹配参数类型)。

最后,允许将 switch 嵌套在其他 case 语句中。如果您需要跳出外部循环或 switch 并且不希望出现歧义,您可以标记循环和开关并使用 break label_name_here; 来指定您想要哪一个打破。对于嵌套循环的 continue 也是如此。

顺便说一句,如果您深入研究 std.traits 内容,您还可以自动生成将 string[] 转换为其他类型参数的包装函数。我希望我的书已经出版了,我在那里写了一些详细的内容,现在不想写完,但是如果你看看 std.traits.ParameterTypeTupleReturnType 在同一个模块中,如果您想尝试的话,可以开始使用。

关于mixins - 从字符串获取类——通过字符串名称调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23076928/

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