digitalmars.D - Eliminating code duplication for static/nonstatic functions
- Andrei Alexandrescu (31/31) Sep 19 2013 Consider a struct that may or may not have state depending on a type
- Andrej Mitrovic (4/6) Sep 19 2013 opDispatch comes to mind. You'd only need two of them, one marked
- Jacob Carlborg (4/6) Sep 19 2013 You cannot overload on "static".
- Andrej Mitrovic (4/8) Sep 19 2013 Can't you read the damn OP example? He's using a static if to
- Andrei Alexandrescu (3/13) Sep 19 2013 I'm not sure I understand how that would work.
- Andrej Mitrovic (45/46) Sep 19 2013 -----
- Andrei Alexandrescu (22/26) Sep 20 2013 [snip]
- Dmitry Olshansky (11/37) Sep 20 2013 Shouldn't it as simple as a mixin-able template that simply forwards all...
- Simen Kjaeraas (26/52) Sep 20 2013 Like this?
- Andrei Alexandrescu (3/27) Sep 21 2013 This is nice. Works with shared, too.
- deadalnix (4/32) Sep 21 2013 You'll be very disapointed when some of your overloads will
- Jacob Carlborg (4/7) Sep 19 2013 Right, sorry.
- Andrej Mitrovic (3/8) Sep 19 2013 Sorry for the harsh response on my part, I wasn't in the mood 5
- safety0ff (8/14) Sep 19 2013 Hello,
- Andrei Alexandrescu (5/19) Sep 20 2013 Nice. If that's what you write while not being very experienced, I'm
- Benjamin Thaut (4/36) Sep 19 2013 Can't we make the compiler deduce the static attribute? If a template
- Andrei Alexandrescu (10/13) Sep 19 2013 That would be nice for this case, but it's a breaking change and I'm not...
- Walter Bright (2/5) Sep 19 2013 static/nonstatic member functions have different ABIs, so no, it would n...
- H. S. Teoh (20/27) Sep 19 2013 There's also the problem of base class methods turning static where you
- Kenji Hara (5/34) Sep 20 2013 Just an idea: string mixin + UDA?
- Andrei Alexandrescu (8/11) Sep 20 2013 That would be nice but would be a language change (and a subtle one...
- Dmitry Olshansky (43/47) Sep 20 2013 It seems like s/string/template and we are there.
- Vladimir Panteleev (12/14) Sep 21 2013 I would like to note that this problem is a specific case of the
Consider a struct that may or may not have state depending on a type parameter: struct S(T) { enum hasState = FieldTypeTuple!T.length || isNested!T; static if (hasState) T _theT; else alias _theT = T; ... } This is really nice because I don't bloat S unnecessarily and I get to use _theT.method() uniformly whether or not it's the type itself or the data member. The duplication problem appears when S itself must define a method that should be static or nonstatic depending on the existence of state. Consider: struct S(T) { ... continued from above ... if (hasState) int method() { return 1 + _theT.method(); } else static int method() { return 1 + _theT.method(); } } In the general case the body of S!T.method() may be of course larger, which makes for a nasty duplication - essentially all but the "static" keyword must be duplicated. Any ideas for a clean solution? I can't get much further than string mixins, which wouldn't be clean :o). Thanks, Andrei
Sep 19 2013
On Thursday, 19 September 2013 at 17:10:43 UTC, Andrei Alexandrescu wrote:Any ideas for a clean solution? I can't get much further than string mixins, which wouldn't be clean :o).opDispatch comes to mind. You'd only need two of them, one marked static and the other one not.
Sep 19 2013
On 2013-09-19 19:20, Andrej Mitrovic wrote:opDispatch comes to mind. You'd only need two of them, one marked static and the other one not.You cannot overload on "static". -- /Jacob Carlborg
Sep 19 2013
On 9/19/13, Jacob Carlborg <doob me.com> wrote:On 2013-09-19 19:20, Andrej Mitrovic wrote:Can't you read the damn OP example? He's using a static if to introduce static/non-static functions, do the same for opDispatch and you'll cut down on code.opDispatch comes to mind. You'd only need two of them, one marked static and the other one not.You cannot overload on "static".
Sep 19 2013
On 9/19/13 12:42 PM, Andrej Mitrovic wrote:On 9/19/13, Jacob Carlborg <doob me.com> wrote:I'm not sure I understand how that would work. AndreiOn 2013-09-19 19:20, Andrej Mitrovic wrote:Can't you read the damn OP example? He's using a static if to introduce static/non-static functions, do the same for opDispatch and you'll cut down on code.opDispatch comes to mind. You'd only need two of them, one marked static and the other one not.You cannot overload on "static".
Sep 19 2013
On 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I'm not sure I understand how that would work.----- module test; import std.traits; struct S(T) { enum hasState = FieldTypeTuple!T.length || isNested!T; static if (hasState) T _theT; else alias _theT = T; private mixin template OpDispatch() { auto opDispatch(string meth, Args...)(Args args) { static if (meth == "method") // specialization ? return 1 + _theT.method(); else return mixin("_theT." ~ meth)(args); } } static if (hasState) mixin OpDispatch!(); else static mixin OpDispatch!(); } struct A { static int method() { return 0; } } struct B { int i; int method() { return i; } } void main() { auto a = S!A(); auto b = S!B(B(1)); assert(a.method == 1); // 1 + A.method() == 1 assert(b.method == 2); // 1 + b.i == 2 assert(S!A.method == 1); // works due to static dispatch // assert(S!B.method == 2); // denied at CT (requires 'this') } -----
Sep 19 2013
On 9/19/13 1:02 PM, Andrej Mitrovic wrote:On 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:[snip] Thanks, that's the simplest and most effective. I reduced it to: struct A { enum hasState = false; private mixin template funDef() { void fun(int x) { writeln(x); } } static if (hasState) mixin funDef!(); else static mixin funDef!(); } void main() { A a; a.fun(42); } I see no way to extract the scaffolding into a library. AndreiI'm not sure I understand how that would work.----- module test;
Sep 20 2013
20-Sep-2013 19:20, Andrei Alexandrescu пишет:On 9/19/13 1:02 PM, Andrej Mitrovic wrote:Shouldn't it as simple as a mixin-able template that simply forwards all methods of a type T (and if it has no state it does so statically). With __traits(allMembers,...) to extract all publics, it must be doable. The end result should be around the following... struct A{ //aliases type or contains state as required mixin extractState!T; } -- Dmitry OlshanskyOn 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:[snip] Thanks, that's the simplest and most effective. I reduced it to: struct A { enum hasState = false; private mixin template funDef() { void fun(int x) { writeln(x); } } static if (hasState) mixin funDef!(); else static mixin funDef!(); } void main() { A a; a.fun(42); } I see no way to extract the scaffolding into a library.I'm not sure I understand how that would work.----- module test;
Sep 20 2013
On 2013-09-20, 17:20, Andrei Alexandrescu wrote:On 9/19/13 1:02 PM, Andrej Mitrovic wrote:Like this? import std.stdio; mixin template maybeStatic(bool isStatic, alias funDef, args...) { static if (isStatic) { static mixin funDef!args; } else { mixin funDef!args; } } struct A { enum hasState = false; private mixin template funDef() { void fun(int x) { writeln(x); } } mixin maybeStatic!(!hasState, funDef); } void main() { A a; a.fun(42); } -- SimenOn 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:[snip] Thanks, that's the simplest and most effective. I reduced it to: struct A { enum hasState = false; private mixin template funDef() { void fun(int x) { writeln(x); } } static if (hasState) mixin funDef!(); else static mixin funDef!(); } void main() { A a; a.fun(42); } I see no way to extract the scaffolding into a library.I'm not sure I understand how that would work.----- module test;
Sep 20 2013
On 9/20/13 8:52 AM, Simen Kjaeraas wrote:This is nice. Works with shared, too. AndreiI see no way to extract the scaffolding into a library.Like this? import std.stdio; mixin template maybeStatic(bool isStatic, alias funDef, args...) { static if (isStatic) { static mixin funDef!args; } else { mixin funDef!args; } } struct A { enum hasState = false; private mixin template funDef() { void fun(int x) { writeln(x); } } mixin maybeStatic!(!hasState, funDef); } void main() { A a; a.fun(42); }
Sep 21 2013
On Friday, 20 September 2013 at 15:20:36 UTC, Andrei Alexandrescu wrote:On 9/19/13 1:02 PM, Andrej Mitrovic wrote:You'll be very disapointed when some of your overloads will disapear.On 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:[snip] Thanks, that's the simplest and most effective. I reduced it to: struct A { enum hasState = false; private mixin template funDef() { void fun(int x) { writeln(x); } } static if (hasState) mixin funDef!(); else static mixin funDef!(); } void main() { A a; a.fun(42); } I see no way to extract the scaffolding into a library. AndreiI'm not sure I understand how that would work.----- module test;
Sep 21 2013
On 2013-09-19 21:42, Andrej Mitrovic wrote:Can't you read the damn OP example? He's using a static if to introduce static/non-static functions, do the same for opDispatch and you'll cut down on code.Right, sorry. -- /Jacob Carlborg
Sep 19 2013
On 9/19/13, Jacob Carlborg <doob me.com> wrote:On 2013-09-19 21:42, Andrej Mitrovic wrote:Sorry for the harsh response on my part, I wasn't in the mood 5 minutes ago. I shouldn't take it out on fellow D programmers.Can't you read the damn OP example? He's using a static if to introduce static/non-static functions, do the same for opDispatch and you'll cut down on code.Right, sorry.
Sep 19 2013
On Thursday, 19 September 2013 at 17:20:53 UTC, Andrej Mitrovic wrote:On Thursday, 19 September 2013 at 17:10:43 UTC, Andrei Alexandrescu wrote:Hello, I decided to try and solve this as an exercise with the opDispatch hint above. I am not very experienced with D, but I am sharing my solution anyway in case it is of interest: http://dpaste.dzfl.pl/3bde7db1 Enjoy/Destroy :)Any ideas for a clean solution? I can't get much further than string mixins, which wouldn't be clean :o).opDispatch comes to mind. You'd only need two of them, one marked static and the other one not.
Sep 19 2013
On 9/19/13 9:59 PM, safety0ff wrote:On Thursday, 19 September 2013 at 17:20:53 UTC, Andrej Mitrovic wrote:Nice. If that's what you write while not being very experienced, I'm really looking forward to what you'll write when you'll be! Thanks, AndreiOn Thursday, 19 September 2013 at 17:10:43 UTC, Andrei Alexandrescu wrote:Hello, I decided to try and solve this as an exercise with the opDispatch hint above. I am not very experienced with D, but I am sharing my solution anyway in case it is of interest: http://dpaste.dzfl.pl/3bde7db1 Enjoy/Destroy :)Any ideas for a clean solution? I can't get much further than string mixins, which wouldn't be clean :o).opDispatch comes to mind. You'd only need two of them, one marked static and the other one not.
Sep 20 2013
Am 19.09.2013 19:10, schrieb Andrei Alexandrescu:Consider a struct that may or may not have state depending on a type parameter: struct S(T) { enum hasState = FieldTypeTuple!T.length || isNested!T; static if (hasState) T _theT; else alias _theT = T; ... } This is really nice because I don't bloat S unnecessarily and I get to use _theT.method() uniformly whether or not it's the type itself or the data member. The duplication problem appears when S itself must define a method that should be static or nonstatic depending on the existence of state. Consider: struct S(T) { ... continued from above ... if (hasState) int method() { return 1 + _theT.method(); } else static int method() { return 1 + _theT.method(); } } In the general case the body of S!T.method() may be of course larger, which makes for a nasty duplication - essentially all but the "static" keyword must be duplicated. Any ideas for a clean solution? I can't get much further than string mixins, which wouldn't be clean :o). Thanks, AndreiCan't we make the compiler deduce the static attribute? If a template method or a method of a template struct / class does not access any of its members it becomes static automatically?
Sep 19 2013
On 9/19/13 12:44 PM, Benjamin Thaut wrote:Can't we make the compiler deduce the static attribute? If a template method or a method of a template struct / class does not access any of its members it becomes static automatically?That would be nice for this case, but it's a breaking change and I'm not sure how confusing it would be in general. Allowing static/nonstatic overloading would help because at least I could do this: int method() { return 1 + _theT.method(); } static if (!hasState) static int method() { return S().method(); } which still is quite a bit of work, but less net duplication. Andrei
Sep 19 2013
On 9/19/2013 12:44 PM, Benjamin Thaut wrote:Can't we make the compiler deduce the static attribute? If a template method or a method of a template struct / class does not access any of its members it becomes static automatically?static/nonstatic member functions have different ABIs, so no, it would not work.
Sep 19 2013
On Thu, Sep 19, 2013 at 01:32:06PM -0700, Walter Bright wrote:On 9/19/2013 12:44 PM, Benjamin Thaut wrote:There's also the problem of base class methods turning static where you didn't intend it to, for example: class Base { // This method is intended to be overridden by derived // classes. void method() { // Oops, didn't access 'this', now we're static. assert(0, "Not implemented"); } } class Derived : Base { int x; override void method() { // NG x++; } } T -- Computers aren't intelligent; they only think they are.Can't we make the compiler deduce the static attribute? If a template method or a method of a template struct / class does not access any of its members it becomes static automatically?static/nonstatic member functions have different ABIs, so no, it would not work.
Sep 19 2013
2013/9/20 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>Consider a struct that may or may not have state depending on a type parameter: struct S(T) { enum hasState = FieldTypeTuple!T.length || isNested!T; static if (hasState) T _theT; else alias _theT = T; ... } This is really nice because I don't bloat S unnecessarily and I get to use _theT.method() uniformly whether or not it's the type itself or the data member. The duplication problem appears when S itself must define a method that should be static or nonstatic depending on the existence of state. Consider: struct S(T) { ... continued from above ... if (hasState) int method() { return 1 + _theT.method(); } else static int method() { return 1 + _theT.method(); } } In the general case the body of S!T.method() may be of course larger, which makes for a nasty duplication - essentially all but the "static" keyword must be duplicated. Any ideas for a clean solution? I can't get much further than string mixins, which wouldn't be clean :o).Just an idea: string mixin + UDA? mixin(hasState ? "" : "static") int method() { return 1 + _theT.method(); } Kenji Hara
Sep 20 2013
On 9/20/13 12:34 AM, Kenji Hara wrote:Just an idea: string mixin + UDA? mixin(hasState ? "" : "static") int method() { return 1 + _theT.method(); }That would be nice but would be a language change (and a subtle one... now we have mixin which introduces attributes that themselves may or may not start with " "). I decided to go with a slightly different design, but the problem remains - there is no simple way to introduce conditional attributes and qualifiers. Andrei
Sep 20 2013
19-Sep-2013 21:10, Andrei Alexandrescu пишет:Consider a struct that may or may not have state depending on a type parameter:[snip]Any ideas for a clean solution? I can't get much further than string mixins, which wouldn't be clean :o).It seems like s/string/template and we are there. This works for me: import std.traits; struct Static{ static int method(){ return 21; } } struct Instance{ int v; //so that it "hasState" int method(){ return 12; } } mixin template Methods() { int method() { return 1 + _theT.method(); } } struct S(T) { enum hasState = FieldTypeTuple!T.length || isNested!T; static if (hasState) T _theT; else alias _theT = T; static if (hasState) mixin Methods!(); else{ static{ mixin Methods!(); } } } void main() { S!Static s1; S!Instance s2; assert(S!Static.method() == 22); assert(s1.method() == 22); assert(s2.method() == 13); assert(s1.sizeof == 1); assert(s2.sizeof == 4); } -- Dmitry Olshansky
Sep 20 2013
On Thursday, 19 September 2013 at 17:10:43 UTC, Andrei Alexandrescu wrote:Consider a struct that may or may not have state depending on a type parameter:I would like to note that this problem is a specific case of the general problem of changing a function's signature based on a compile-time value. The same problem exists with other attributes, and varying the presence of a template or function parameter. One example was that I wanted to define an overload set of function templates, where in some overloads, some parameters were function parameters, and in other overloads, the same parameters were template parameters (there was a significant optimization opportunity when the parameters were known at compile-time).
Sep 21 2013