passing duck-typed objects and retaining full type information
Freddy via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Tue Nov 11 17:21:03 PST 2014
On Tuesday, 11 November 2014 at 19:23:39 UTC, Adam Taylor wrote:
> * i apologize in advance, this is my first post -- the code
> formatting probably wont turn out so great...
>
> I have a bunch of duck typed interfaces for "containers"
> similar to what you would find in std.range.
>
> i.e.
> template isContainer(C)
> {
> enum bool isContainer = is(typeof(
> (inout int = 0)
> {
> C c = C.init;
> ...
> }));
> }
>
> template canRemoveFromContainer(C)
> {
> enum bool canRemoveFromContainer = isContainer!C &&
> is(typeof(
> (inout int = 0)
> {
> C c = C.init;
> c.remove();
> }));
> }
>
> Now what i want to do is pass some such "container" object to
> an interface function:
>
> interface MyInterface
> {
> void filterCollisions(S)(S collisionCandidates)
> if(canRemoveFromContainer!S)
> }
>
> but of coarse templates and interfaces don't get along so well.
> so...so far as I know i would need to do something like this:
>
>
> interface MyInterface
> {
> final void filterCollisions(S)(S collisionCandidates)
> if(canRemoveFromContainer!S)
> {
> filterCollisionsImpl(...);
> }
>
> void filterCollisionsImpl(...)
>
> }
>
>
> and pass something to filterCollisionsImpl that is a "proper"
> class or interface type.
>
> So here's the problem: many of the "duck-typed" interfaces
> cannot be converted to proper interfaces without losing
> something. So is there ANY way to pass in
> a very basic class or interface Container type and call the
> remove function on it? Here's what i've tried:
>
> interface Container(C)
> {
> ...
> }
>
> template ContainerObject(C) if (isContainer!(Unqual!C)) {
> static if (is(C : Container!(ElementType!C))) {
> alias ContainerObject = C;
> } else static if (!is(Unqual!C == C)) {
> alias ContainerObject = ContainerObject!(Unqual!C);
> } else {
>
> static if (__traits(compiles, { enum e = C.ValueType; })) {
> alias ValueType = C.ValueType;
> } else {
> alias ValueType = ElementType!C;
> }
>
> class ContainerObject : Container!ValueType {
> C _container;
>
> this(C container) {
> this._container = container;
> }
>
> static if(canRemoveFromContainer!C) {
> size_t remove()
> {
> return _container.remove();
> }
> }
> }
> }
> }
>
> ContainerObject!C containerObject(C)(C container) if
> (isContainer!C) {
> static if (is(C : Container!(ElementType!C))) {
> return container;
> } else {
> return new ContainerObject!C(container);
> }
> }
>
>
> interface MyInterface
> {
> final void filterCollisions(S)(S collisionCandidates)
> if(canRemoveFromContainer!S)
> {
> auto container = containerObject(collisionCandidates);
> container.remove(); // works just fine -- have the complete
> type info at instantiation site
> filterCollisionsImpl();
> }
>
> void filterCollisionsImpl(Container!string collisionCandidates)
> collisionCandidates.remove(); // error -- some type info is
> lost here, only have a Container!string which doesn't have a
> remove function.
> }
Not entirly sure of what you asking for,but have you tried
inhertance?
----
interface Base(C){
/+...+/
}
interface Derived(C):Base!C{
/+...+/
}
----
More information about the Digitalmars-d-learn
mailing list