Build interface from abstract class
Simen Kjærås
simen.kjaras at gmail.com
Wed May 30 10:31:27 UTC 2018
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
More information about the Digitalmars-d-learn
mailing list