考虑以下代码:
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提供此功能。