如何在D中扩展功能?

时间:2016-07-19 20:01:02

标签: d

考虑以下代码:

template isSend(T){
    import std.meta;
    import std.traits;
    alias fieldNames = FieldNameTuple!T;
    static if(fieldNames.length == 1 && fieldNames[0] == ""){
        enum isSend = true;
    }
    else{
        alias toType(string s) = typeof(__traits(getMember, T, s));
        enum isSend = allSatisfy!(.isSend, staticMap!(toType, fieldNames));
    }
}

这是超级hacky,但它基本上做的是将特定类型标记为sendable。如果类型没有成员,则默认情况下它被认为是可发送的。如果所有成员都是sendable,也会被视为sendable

struct Foo{}

// sendable because all members are sendable
struct Bar{
    int i;
}

// not sendable because we set it explicitly to false
struct Baz{}
enum isSend(T: Baz) = false;

// sendable because Bar is sendable
struct Test1{
    Bar bar;
}

//not sendable because Baz is not sendable
struct Test2{
    Baz baz;
}

这很好,因为所有内容都在同一个模块中,但是一旦我尝试为定义isSend的模块之外的其他类型实现isSend,它就会崩溃。

示例非常简单,我可以使用UDA's来实现它。

另一个例子是

auto arr = iota(0, 100).array;

这在phobos中定义并创建一个数组,但如果每个数据结构都必须定义自己的函数,那将会有点尴尬。考虑这样的事情

int[] arr = iota(0, 100).collect!(int[]);
Array!int arr1 = iota(0, 100).collect!(Array!int);

如何实现这一目标?

auto collect(Iter, T)(ref Iter iter){...}
auto collect(Iter, A, T: Array!A)(ref Iter iter){...}

我认为问题是不同模块的collect会有所不同,有没有办法说我想在模块b中为模块b创建collect的重载/特化? / p>

我还有哪些其他选择来扩展功能?

更新

基本上这就是我想要实现的目标

int[] arr = iota(0, 100).collect!(int[]);
Array!int arr1 = iota(0, 100).collect!(Array!int);
....

想象一下,collect将在某个库中定义。现在我有另一个容器,我们称之为List。我希望能够在List!T

上拨打电话
List!int arr2 = iota(0, 100).collect!(List!int);

collect无法与List一起使用,因为List来自其他库。现在,我需要扩展collect的功能,以便与List!T一起使用。

可以用D表示collect

我尝试使用模板专业化来实现它,我不确定这是否是正确的工具。

T collect(T, Range)(auto ref Range range){
    static assert(false, "Collect is not implemented for " ~ T.stringof);
}

T collect(A, T: Array!A, Range)(auto ref Range range)
    if(isInputRange!Range){
    auto arr = Array!A();

    foreach(ref e; range){
        arr.insert(e);
    }

    return arr;
}

现在可以像这样使用

Array!int arr = iota(0, 100).collect!(int, Array!int)(); //ugly

Rust通过collect提供此功能。

0 个答案:

没有答案