Я только начинаю изучать язык программирования D и с удовольствием играю с ключевыми словами делегатов и функций. Я пытаюсь реализовать (только для моего собственного учебного процесса) знаменитый класс Deferred из Twisted (написанный на Python).
Мне просто интересно, есть ли какие-то хитрости, чтобы выделить такой код:
class Deferred(ResultType)
{
alias ResultType delegate(ResultType) CallbackType;
private CallbackType[2] _callbacks[];
private bool _running;
private uint _paused;
void addCallback(CallbackType cb)
{
this._callbacks ~= [cb, cast(CallbackType) null];
}
void addCallback(void function() f)
{
this.addCallback(
(ResultType res) { f(); return res; }
);
}
void addCallback(void function(ResultType) f)
{
this.addCallback(
(ResultType res) { f(res); return res; }
);
}
void addCallback(ResultType function() f)
{
this.addCallback(
(ResultType res) { return f(); }
);
}
void addCallback(ResultType function(ResultType) f)
{
this.addCallback(
(ResultType res) { return f(res); }
);
}
}
Цель состоит в том, чтобы позволить пользователю не передавать делегат CallbackType
, а какую-то функцию, с или без правильного аргумента / возвращаемого типа.
Я что-то упускаю из виду?
[РЕДАКТИРОВАТЬ]: С советами Mehrdad ответ может быть что-то вроде этого:
class Deferred(ResultType)
{
alias ResultType delegate(Deferred, ResultType) CallbackType;
private CallbackType[2] _callbacks[];
void addCallback(T)(T cb)
{
this._callbacks ~= [this._makeConvenient(cb), cast(CallbackType) null];
}
private CallbackType _makeConvenient(T)(T f)
{
alias traits.ReturnType!(f) ReturnType;
alias traits.ParameterTypeTuple!(f) Params;
return (Deferred d, ResultType res)
{
ReturnType wrapper()
{
static if (Params.length == 2)
{
static if (is(Params[0] == Deferred!(ResultType)) && is(Params[1] == ResultType))
return f(this, res);
else
static assert(false, "Cannot wrap given callback: Wrong arguments types");
}
else static if (Params.length == 1)
{
static if (is(Params[0] == Deferred!(ResultType)))
return f(this);
else static if (is(Params[0] == ResultType))
return f(res);
else
static assert(false, "Cannot wrap given callback: Wrong argument type");
}
else static if (Params.length == 0)
return f();
else
static assert(false, "Cannot wrap given callback: Wrong argument number");
}
static if (is(ReturnType == void)) { wrapper(); return res; }
else static if (is(ReturnType == ResultType)) { return wrapper(); }
else static assert(false, "Cannot wrap given callback: Wrong return type");
};
}
}
Я в правильном направлении? Есть ли заметные проблемы с производительностью?