Bug 1023 – Struct implementing interfaces and struct member enumeration
Status
RESOLVED
Resolution
WORKSFORME
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2007-03-04T14:47:07Z
Last change time
2018-05-15T13:30:08Z
Assigned to
No Owner
Creator
Lars Ivar Igesund
Comments
Comment #0 by larsivar — 2007-03-04T14:47:07Z
Structs in D are very simple which is good, but in some cases they are just
too simple. In many cases you would want to handle struct instances as if
they were Object derivates, by calling methods on them, methods that
implement an interface. The most obvious example is toUtf8 (or toString).
As it is now, for instance in a formatter, if it detects that the input is
a struct, you have no way of figuring out whether the struct implements an
interface or not.
This is thus a request to make it possible to say that a struct implements
an interface and thus can be typeid'ed on other types (interfaces) than
those of the structs themselves. An enumeration of the methods of the
struct would also be nice.
I started a thread in the NG out of old habit, but I think this is the more correct place.
Comment #1 by larsivar — 2007-03-04T15:04:37Z
I may add that a complete, flexible, extensible formatter like the one in .Net (which is lucky enough to only have to care about objects) is impossible without some interface support for structs in D.
Comment #2 by smjg — 2007-03-05T09:13:14Z
I'm not sure what I think of this idea. There are a few difficulties - some operations would have to check whether an interface reference references a struct or class object. And so casting even to Object would have to have a bit of runtime overhead to validate it.
Moreover, I'm not sure if the necessary conversion of the struct from value semantics to reference semantics are likely to cause confusion for some/in some circumstances.
(In reply to comment #0)
> I started a thread in the NG out of old habit, but I think this is the more
> correct place.
Actually, it was once said that feature requests shouldn't be posted on this particular Bugzilla, but the policy seems to have faded away lately. I'm not sure.
Comment #3 by larsivar — 2007-03-05T09:27:35Z
(In reply to comment #2)
> I'm not sure what I think of this idea. There are a few difficulties - some
> operations would have to check whether an interface reference references a
> struct or class object. And so casting even to Object would have to have a bit
> of runtime overhead to validate it.
>
> Moreover, I'm not sure if the necessary conversion of the struct from value
> semantics to reference semantics are likely to cause confusion for some/in some
> circumstances.
There will certainly be technical difficulties, and as such the second request, enumeration of the methods, would be the half-assed, easy way to do it (all necessary information in the typeinfo, but for a larger interface you may have to check for a long list of methods before you know that the correct interface is implemented).
I would be happy for the functionality to ask whether a struct is of type foo, using typeid, not necessarily pass it along as type foo. It would probably cause some inconsistency somewhere in the system though as "struct MyType : IFoo { }" probably would make people expect that they could pass an instance to "void bar(IFoo foo);".
>
> (In reply to comment #0)
> > I started a thread in the NG out of old habit, but I think this is the more
> > correct place.
>
> Actually, it was once said that feature requests shouldn't be posted on this
> particular Bugzilla, but the policy seems to have faded away lately. I'm not
> sure.
>
Yes, there was a discussion about that, at which point most references to Bug were changed to Issue.
Comment #4 by default_357-line — 2007-03-08T03:35:22Z
[email protected] schrieb:
> http://d.puremagic.com/issues/show_bug.cgi?id=1023
>
> Summary: Struct implementing interfaces and struct member
> enumeration
> Product: D
> Version: unspecified
> Platform: All
> OS/Version: All
> Status: NEW
> Severity: enhancement
> Priority: P2
> Component: DMD
> AssignedTo: [email protected]
> ReportedBy: [email protected]
>
>
> Structs in D are very simple which is good, but in some cases they are just
> too simple. In many cases you would want to handle struct instances as if
> they were Object derivates, by calling methods on them, methods that
> implement an interface. The most obvious example is toUtf8 (or toString).
> As it is now, for instance in a formatter, if it detects that the input is
> a struct, you have no way of figuring out whether the struct implements an
> interface or not.
>
> This is thus a request to make it possible to say that a struct implements
> an interface and thus can be typeid'ed on other types (interfaces) than
> those of the structs themselves. An enumeration of the methods of the
> struct would also be nice.
>
> I started a thread in the NG out of old habit, but I think this is the more
> correct place.
>
>
Consider the following code.
import std.stdio, std.traits;
struct a { void test() { } }
struct b { void Test() { } }
struct c { int Test() { return 0; } }
void test(T)() {
T t=void;
static if (is(typeof(t.Test)==function)) {
writefln(T.mangleof, " has Test, returns ", typeid(ReturnType!(t.Test)));
}
else writefln(T.mangleof, " lacks Test");
}
void main() {
test!(a); test!(b); test!(c);
}
Thus, we can check if a struct implements a series of functions, and check their return values and the parameters they take.
Does that come close to what you need?
greetings --downs
Comment #5 by default_357-line — 2007-03-08T03:45:12Z
Downs schrieb:
> [email protected] schrieb:
>> http://d.puremagic.com/issues/show_bug.cgi?id=1023
>>
>> Summary: Struct implementing interfaces and struct member
>> enumeration
>> Product: D
>> Version: unspecified
>> Platform: All
>> OS/Version: All
>> Status: NEW
>> Severity: enhancement
>> Priority: P2
>> Component: DMD
>> AssignedTo: [email protected]
>> ReportedBy: [email protected]
>>
>>
>> Structs in D are very simple which is good, but in some cases they are
>> just
>> too simple. In many cases you would want to handle struct instances as if
>> they were Object derivates, by calling methods on them, methods that
>> implement an interface. The most obvious example is toUtf8 (or toString).
>> As it is now, for instance in a formatter, if it detects that the
>> input is
>> a struct, you have no way of figuring out whether the struct
>> implements an
>> interface or not.
>>
>> This is thus a request to make it possible to say that a struct
>> implements
>> an interface and thus can be typeid'ed on other types (interfaces) than
>> those of the structs themselves. An enumeration of the methods of the
>> struct would also be nice.
>>
>> I started a thread in the NG out of old habit, but I think this is the
>> more
>> correct place.
>>
>>
> Consider the following code.
>
> import std.stdio, std.traits;
>
> struct a { void test() { } }
> struct b { void Test() { } }
> struct c { int Test() { return 0; } }
>
> void test(T)() {
> T t=void;
> static if (is(typeof(t.Test)==function)) {
> writefln(T.mangleof, " has Test, returns ",
> typeid(ReturnType!(t.Test)));
> }
> else writefln(T.mangleof, " lacks Test");
> }
>
> void main() {
> test!(a); test!(b); test!(c);
> }
>
> Thus, we can check if a struct implements a series of functions, and
> check their return values and the parameters they take.
> Does that come close to what you need?
> greetings --downs
Nevermind, I see what he means.
And I agree, more typeinfo for structs would be a good thing, especially for using with the new mixin syntax.
Comment #6 by ah08010-d — 2010-10-22T01:49:18Z
I'd like to bump this request, and maybe make it a little more specific. What I'm looking for is essentially a "duck interface" - that is, "this type supports these methods, carry on." Except that I want strong enforcement - "you told me that you would support these methods, but you don't. Error."
Adding 'static interface' might be the way to differentiate between class-interface and struct-interface. This is by analogy with the behavior of static in a nested-function context (has no 'this', etc.).
In my case, struct is the right mechanism for speed and stack allocation, while the interface is nice to provide a single point to document and to have the compiler verify. If I've forgotten one of the eleventy-seven possible specializations, I want the compiler to tell me.
So for example, if an interface is declared "static interface" or "duck interface" or whatever, then getting a reference to it is impossible, because it makes no promises about the underlying type. It could be a class, it could be a struct, it could be an enum.
However, you could mix in duck interfaces anywhere, and the compiler verify them. And similarly, you could use them to annotate symbols, but that might need a little syntactic sugar:
static interface Duck;
class Base;
class Derived : Base, Duck;
struct Mallard : Duck;
auto obj = new Derived();
obj.quack();
auto s = Mallard();
s.quack();
Comment #7 by hoganmeier — 2011-12-13T11:56:26Z
(In reply to comment #6)
> Adding 'static interface' might be the way to differentiate between
> class-interface and struct-interface.
..
> In my case, struct is the right mechanism for speed and stack allocation, while
> the interface is nice to provide a single point to document and to have the
> compiler verify.
Exactly!
Phobos circumvents the problem by using lots of templates in constraints:
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r = void; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}
While this works fine, it does have some disadvantages.
It adds lots of overhead cause all of that code must be evaluated with errors gagged, mustn't alter the AST and whatever. Also there are a lot of bugs introduced by that here in bugzilla.
Furthermore there are no useful error messages with template constraints, so you don't even know what exactly went wrong when you implemented the interface.
> So for example, if an interface is declared "static interface" or "duck
> interface" or whatever, then getting a reference to it is impossible, because
> it makes no promises about the underlying type.
Yep, but one would need them as parameters. Maybe
foo(Bla b)
with Bla being a static interface could be shorthand for a compiler internal equivalent of the currently used, ugly
foo(Blub)(Blub b) if (conformsToBlaStructure!Blub)
OTOH, how to express if you want a struct conforming to multiple structural interfaces?
Comment #8 by dmitry.olsh — 2018-05-15T13:30:08Z
> An enumeration of the methods of the
struct would also be nice.
__trait(getMembers, ...)
Far as duck typing goes, this may produce a DIP on compile-time interfaces (a-la concepts).
And we have had good library solutions that check all of boxes for a long time now, see:
https://github.com/atilaneves/concepts
Which has `models` UDA to check if struct follows interface statically.