C++ guys hate static_if?
anonymous
anonymous at example.com
Tue Mar 12 00:58:14 PDT 2013
By now, I'm suspecting that I'm missing the point entirely, but
here it is.
The idea is this:
Given
interface A {...}
interface B : A {...}
struct S {supposed to implement B}
use alias this to enable implicit conversions:
S to Concept!(B, S)
Concept!(B, S) to Concept!(A, S)
The number of alias this hops then decides which overload is
taken.
No rights reserved.
import std.traits: BaseTypeTuple;
mixin template implements(Iface) {
@property inout(Concept!(Iface, typeof(this))) _concept()()
inout {
return typeof(return)(this);
}
alias _concept this;
// ensure that the interface is implemented
alias typeof(this) Self;
private class _Tester : Iface {
Self s;
mixin ForwardInterface!(s, Iface);
}
}
struct Concept(Iface, Impl) {
Impl impl;
mixin ForwardInterface!(impl, Iface);
alias BaseTypeTuple!Iface B;
static if(B.length == 1) {
@property inout(Concept!(B, typeof(impl))) _concept()()
inout {
return typeof(return)(impl);
}
alias _concept this;
} else {
// because multiple alias this aren't here yet
static assert(B.length == 0);
}
}
import std.traits: ParameterTypeTuple, ReturnType;
import std.string: format;
mixin template ForwardInterface(alias target, Iface) {
mixin ForwardMembers!(target, Iface, __traits(allMembers,
Iface));
}
mixin template ForwardMembers(alias target, Iface, memberNames
...) {
static if(memberNames.length > 0) {
mixin ForwardOverloads!(target, memberNames[0],
__traits(getOverloads, Iface, memberNames[0]));
mixin ForwardMembers!(target, Iface, memberNames[1 .. $]);
}
}
mixin template ForwardOverloads(
alias target,
string memberName,
overloads ...
) {
static if(overloads.length > 0) {
alias overloads[0] o;
mixin(format(
q{
ReturnType!o %1$s(ParameterTypeTuple!o args)
%2$-(%s %) {
target.%1$s(args);
}
},
memberName,
[
(is(typeof(o) == immutable) ? "immutable" : ""),
(is(typeof(o) == const) ? "const" : ""),
(is(typeof(o) == shared) ? "shared" : "")
]
));
mixin ForwardOverloads!(target, memberName, overloads[1
.. $]);
}
}
// example from
http://forum.dlang.org/post/qqnwpprluchyaphvammf@forum.dlang.org
interface A1 {void foo();}
interface A2 : A1 {void bar();}
interface B1 {void fun();}
interface B2 : B1 {void gun();}
struct S1 {
mixin implements!A2;
void foo() {}
void bar() {}
}
struct S2 {
mixin implements!B2;
void fun() {}
void gun() {}
}
int dostuff(X, Y)(Concept!(A1, X) a, Concept!(B1, Y) b) {return
1;}
int dostuff(X, Y)(Concept!(A2, X) a, Concept!(B1, Y) b) {return
2;}
import std.stdio;
void main() {
S1 s1;
S2 s2;
writeln(dostuff(s1, s2)); // calls the more specialized
Overload-2
}
// But, if we add the following overload, then the above
// function call dostuff(s1, s2) doesn't know whether to
// call Overload-2 or, the equally specialized, Overload-3:
int dostuff(X, Y)(Concept!(A1, X) a, Concept!(B2, Y) b) {return
3;}
// And, if we add yet another, more specialized, overload,
// then the previous ambiguity goes away:
int dostuff(X, Y)(Concept!(A2, X) a, Concept!(B2, Y) b) {return
4;}
More information about the Digitalmars-d
mailing list