September 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.
September 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:
> >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.

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.
September 20, 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:
>> 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.

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 :)
September 20, 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


September 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
September 20, 2013
On 9/19/13 9:59 PM, safety0ff wrote:
> 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:
>>> 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.
>
> 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 :)

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,

Andrei

September 20, 2013
On 9/19/13 1:02 PM, Andrej Mitrovic wrote:
> On 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>> I'm not sure I understand how that would work.
>
> -----
> module test;
[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.


Andrei

September 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


September 20, 2013
20-Sep-2013 19:20, Andrei Alexandrescu пишет:
> On 9/19/13 1:02 PM, Andrej Mitrovic wrote:
>> On 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>> I'm not sure I understand how that would work.
>>
>> -----
>> module test;
> [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.

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 Olshansky
September 20, 2013
On 2013-09-20, 17:20, Andrei Alexandrescu wrote:

> On 9/19/13 1:02 PM, Andrej Mitrovic wrote:
>> On 9/19/13, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>> I'm not sure I understand how that would work.
>>
>> -----
>> module test;
> [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.

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);
}

-- 
  Simen