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