On Monday, 28 May 2018 at 20:13:49 UTC, DigitalDesigns wrote:
I do not think this is a problem in D. Infinite recursion can always be terminated with appropriate means.

1. Use attributes. methods in class A should be marked as being for the interface. When added to the interface they will not have the attribute so will not be picked up again.

2. Your method of function creation does not pick up attributes and other factors so it is weak.

Here is my solution that does not solve problem 2:

[Neat stuff]

Neat, but as you say it doesn't handle attributes or UDAs. The use of stringof is also a red flag - the same name can apply to different types in different scopes, and aliases may confuse it. Here's a version that solves both of those issues:


import std.array : join;
import std.meta : ApplyLeft, staticMap, Filter, Alias;
import std.traits;

enum isPublic(alias overload) = Alias!(__traits(getProtection, overload) == "public");

interface InterfaceFromClass(T, alias filter = isPublic)
{
static foreach (overload; Filter!(filter, staticMap!(ApplyLeft!(MemberFunctionsTuple, T), __traits(derivedMembers, T)))) mixin("@(__traits(getAttributes, overload)) "~attributes!overload~" ReturnType!overload "~__traits(identifier, overload)~"(Parameters!overload);");
}

string attributes(alias overload)()
{
enum attrs = Filter!(ApplyLeft!(hasFunctionAttributes, overload), "pure", "nothrow", "ref", "@property", "@trusted", "@safe", "@nogc", "@system", "const", "immutable", "inout", "shared", "return", "scope");
    return [attrs].join(" ");
}

alias A = InterfaceFromClass!C;

abstract class C : A
{
    int n;
    @("InterfaceMembers")
    {
        @(3) ref int foo(ref int a) { return n; }
        @(19) @safe void bar() { }
    }
}

// https://issues.dlang.org/show_bug.cgi?id=18915
// class D : C {}

static assert([__traits(allMembers, A)] == ["foo", "bar"]);
static assert(functionAttributes!(A.foo) == functionAttributes!(C.foo)); static assert(functionAttributes!(A.bar) == functionAttributes!(C.bar));
static assert(is(Parameters!(A.foo) == Parameters!(C.foo)));
static assert(is(Parameters!(A.bar) == Parameters!(C.bar)));

Note the link to issue 18915 (that's your 'string mixin output works...' post). I believe if we can fix that, the above should work.

--
  Simen

Reply via email to