gpt4 book ai didi

metaprogramming - 鸭子类型(duck typing)D

转载 作者:行者123 更新时间:2023-12-01 16:21:00 26 4
gpt4 key购买 nike

我是 D 新手,我想知道是否可以方便地进行编译时检查鸭子类型(duck typing)。

例如,我想定义一组方法,并要求为传递给函数的类型定义这些方法。它与 D 中的接口(interface)略有不同,因为我不必在任何地方声明“类型 X 实现接口(interface) Y”——方法就会被找到,否则编译会失败。另外,最好允许这种情况发生在任何类型上,而不仅仅是结构和类。我能找到的唯一资源是 this email thread ,这表明以下方法是实现此目的的一个不错的方法:

void process(T)(T s)
if( __traits(hasMember, T, "shittyNameThatProbablyGetsRefactored"))
// and presumably something to check the signature of that method
{
writeln("normal processing");
}

...并建议您可以将其放入库调用 Implements 中,以便可以实现以下功能:

struct Interface {
bool foo(int, float);
static void boo(float);
...
}

static assert (Implements!(S, Interface));
struct S {
bool foo(int i, float f) { ... }
static void boo(float f) { ... }
...
}

void process(T)(T s) if (Implements!(T, Interface)) { ... }

是否可以对未在类或结构中定义的函数执行此操作?还有其他/新的方法吗?有做过类似的事情吗?

显然,这组约束类似于 Go 的类型系统。我并不是想引发任何口水战 - 我只是以 Go 也能很好地工作的方式使用 D。

最佳答案

这实际上是 D 中非常常见的事情。这就是范围的工作原理。例如,最基本的范围类型 - 输入范围 - 必须具有 3 个功能:

bool empty();  //Whether the range is empty
T front(); // Get the first element in the range
void popFront(); //pop the first element off of the range

模板化函数然后使用 std.range.isInputRange 检查类型是否是有效范围。例如,最基本的重载 std.algorithm.find 看起来像

R find(alias pred = "a == b", R, E)(R haystack, E needle)
if (isInputRange!R &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{ ... }

isInputRange!Rtrue如果R是有效的输入范围,且 is(typeof(binaryFun!pred(haystack.front, needle)) : bool)true如果pred接受haystack.frontneedle并返回一个可隐式转换为 bool 的类型。因此,这种重载完全基于静态鸭子类型(duck typing)。

至于isInputRange它本身看起来像

template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r = void; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}

它是一个同名模板,因此当使用它时,它会被替换为其名称的符号,在本例中是 bool 类型的枚举。那booltrue如果表达式的类型为非 voidtypeof(x)结果 void如果表达式无效;否则,它是表达式 x 的类型。和is(y)结果 true如果y是非 void 。所以,isInputRange最终将是true如果typeof中的代码表达式编译,并且 false否则。

isInputRange中的表达式验证您是否可以声明 R 类型的变量,即R有一个名为 empty 的成员(无论是函数、变量还是其他)可以在 R 的条件下使用有一个名为 popFront 的函数它不带任何参数,并且 R已有成员(member)front它返回一个值。这是输入范围所需的 API,以及 typeof 内的表达式如果 R 将编译遵循该 API,因此 isInputRange将是true对于那种类型。否则,它将是 false .

D 的标准库有很多这样的同名模板(通常称为特征),并在其模板约束中大量使用它们。 std.traits 尤其是其中有相当多的。因此,如果您想要更多有关如何编写此类特征的示例,您可以查看那里(尽管其中一些相当复杂)。这些特征的内部并不总是特别漂亮,但它们确实很好地封装了鸭子类型(duck typing)测试,以便模板约束更加清晰和更容易理解(如果直接将此类测试插入其中,它们会变得非常非常丑陋)。

所以,这是 D 中静态鸭子类型(duck typing)的正常方法。确实需要一些练习才能弄清楚如何写好它们,但这是标准方法,而且它有效。有人建议尝试想出类似于您的 Implements!(S, Interface) 的东西。建议,但目前还没有任何实际成果,而且这种方法实际上不太灵活,使其不适合很多特征(尽管它肯定可以与基本特征一起使用)。无论如何,我在这里描述的方法是目前执行此操作的标准方法。

此外,如果您对范围不太了解,我建议您阅读 this .

关于metaprogramming - 鸭子类型(duck typing)D,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16578676/

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