Re: Struct constructor, opCall mess.

2014-02-25 Thread Remo

On Tuesday, 25 February 2014 at 07:59:33 UTC, Maxim Fomin wrote:
On Monday, 24 February 2014 at 14:14:43 UTC, Tobias Pankrath 
wrote:

On Monday, 24 February 2014 at 13:56:01 UTC, Remo wrote:

Hi,

right now I am truing to figure out how the constructors 
behave in D2.


Question 1: why it is not possible to create custom ctor for 
struct?


The design of D relies on the fact that every type has a 
T.init property that is known to the compiler and used when in 
C++ the default ctor would get called. In constructors you can 
rely on (this == T.init), for example.


You need to pick one T.init or default constructors and D 
picked T.init.


The design of D relies on Andrei opinion. He is indeed 
convinced that default constructors are impossible.


However, you can write "default constructor" right now like:

struct S
{
   Type t;
   this(int)
   {
  t = whather_is_callable_in_CTFE();
   }
}

enum E : S
{
   A = S(0)
}

void main()
{
  E e;
  assert (e.t == whather_is_callable_in_CTFE());
}

Since compiler does this, it can also accept straight syntax 
and semantic:


struct S
{
   Type t;
   this() // proxibited default constructor now
   {
  t = whather_is_callable_in_CTFE();
   }
}

What D really lacks is ability to call function in runtime 
after struct instance creation like:


struct S
{
   @runtime this() {}
   ~this(){}
}

lowering to:
S s;
s.__runtime_ctor();

However, since compiler does this all over the place 
(postblits, copy constructors, destructors, etc.) There is no 
conceptual difference between having:


S s
s.__runtime_ctor();

and

S s;
s.__dtor();

In other words, there is no objective necessity not to have 
compile time and runtime default struct constructors since 
compiler already heavily does conceptually and technically 
similar things.


Thanks for all this replies.
Now I have better idea how it supposed to work.

Yes something like @runtime this() {} would be really great!

https://d.puremagic.com/issues/show_bug.cgi?id=3438
I think at some point we'll need to support default 
constructors that execute

code.
This was posted 2009-10-23 and now years later it is still not 
possible. :(



Unfortunately this problems and workarounds makes porting C++ to 
D2 more complicated.




Here are is also a small experiment that also show that 'ref' is 
also necessary in D2 just like in C++.
There seems to be no optimization for this so using 'in' or 
nothing at all is slower and may have side effects.


http://melpon.org/wandbox/permlink/FyaksIPW4u1dNpwh

http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue%2C%22colouriseAsm%22%3Atrue}%2C%22compilers%22%3A[{%22sourcez%22%3A%22JYWwDg9gTgLgBAZxgEwHROcCBuAULgegIFcFgA7AczjCgpgDM4AjAUwGMBDU1uYeLjwSIQnADZjWUOJwQJWIZmICecdhGS9ZcAO50YrMeVT4kUYu3gBlXAG9ccR33LxgeJ3AdOYAC2AIACno%2BAEp7Dw9gOABePncIx1p6BgCAIis1GGg4AFIogB1yVIAaYBDsJy9HAF8qzw8iKAUIADcKaiamHyktcmQ4ZCzpHWAJFl4kl1Z%2BgGY4GFBWBBMPTrgMiDAAQTlgSnIAtfVyJACrEMQwuo9JxjSN7d39uELU8sqExyjY5bcvAEh%2Fk0YMQoOR5n4EHh%2FrUPHUAH6%2BfwBK6fW4pdIDIYvIrvD5OWq1XAtCDAfqiCgoux1DIIACM8UcRFpACYYutGetEHNYlYUZz6eyEDM8NUgAAA%3D%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%22}]}


Re: Struct constructor, opCall mess.

2014-02-25 Thread Maxim Fomin
On Monday, 24 February 2014 at 14:14:43 UTC, Tobias Pankrath 
wrote:

On Monday, 24 February 2014 at 13:56:01 UTC, Remo wrote:

Hi,

right now I am truing to figure out how the constructors 
behave in D2.


Question 1: why it is not possible to create custom ctor for 
struct?


The design of D relies on the fact that every type has a T.init 
property that is known to the compiler and used when in C++ the 
default ctor would get called. In constructors you can rely on 
(this == T.init), for example.


You need to pick one T.init or default constructors and D 
picked T.init.


The design of D relies on Andrei opinion. He is indeed convinced 
that default constructors are impossible.


However, you can write "default constructor" right now like:

struct S
{
   Type t;
   this(int)
   {
  t = whather_is_callable_in_CTFE();
   }
}

enum E : S
{
   A = S(0)
}

void main()
{
  E e;
  assert (e.t == whather_is_callable_in_CTFE());
}

Since compiler does this, it can also accept straight syntax and 
semantic:


struct S
{
   Type t;
   this() // proxibited default constructor now
   {
  t = whather_is_callable_in_CTFE();
   }
}

What D really lacks is ability to call function in runtime after 
struct instance creation like:


struct S
{
   @runtime this() {}
   ~this(){}
}

lowering to:
S s;
s.__runtime_ctor();

However, since compiler does this all over the place (postblits, 
copy constructors, destructors, etc.) There is no conceptual 
difference between having:


S s
s.__runtime_ctor();

and

S s;
s.__dtor();

In other words, there is no objective necessity not to have 
compile time and runtime default struct constructors since 
compiler already heavily does conceptually and technically 
similar things.


Re: Struct constructor, opCall mess.

2014-02-24 Thread Maxim Fomin

On Monday, 24 February 2014 at 19:41:57 UTC, Remo wrote:

For Vector example this works pretty well this way.
But my main problem is more complicated.

extern(C)  int init(ref CWrapper p);
extern(C) void free(ref CWrapper p);

struct CWrapper
{
  //some data that must be the same at C side.
  Data m_data;

  this() {
 init(&this);
  }
  ~this() {
 free(&this);
  }
}

How to do something like this in D ?
Using class appears for me to be wrong direction.



1) Please comment after previous speaker, not before.

You can't avoid default struct constructor problem if functions 
which you call in constructors are not at least CTFEable because 
you would need to call them if you wish to define default struct 
constructor. Since this is not your case, you can do:


2) You can use static OpCall, Voldemort type or alias this. In 
case of alias this it looks like:


extern(C) int printf(const char*, ...);

extern(C)  int init(CWrapper* p) { printf("init\n"); return 0; }
extern(C) void d_free(CWrapper* p) { printf("free\n"); }

struct Data { void do_something(){} }

struct CWrapper
{
  //some data that must be the same at C side.
  Data m_data;
  bool m_init;

  /*this(int) {
 init(&this);
  }*/
  ~this() {
 d_free(&this);
  }
  Data get()
  {
  if (!m_init)
  init(&this);
  return m_data;
  }
alias get this;
}


void main()
{
CWrapper cw;
cw.do_something();

}

In case of Voldermort struct some struct is defined inside 
function, so the only way (in theory) to create an instance is to 
call that function. It is inconviniet but guarantees that you 
will not have non initialzed structs (in theory).


extern(C) int printf(const char*,...);


auto make_struct()
{
struct Data{}
struct CWrapper
{
  extern(C)  int m_init(CWrapper* p){ return 0; }
  extern(C) void m_free(CWrapper* p){ printf("free\n");}
  //some data that must be the same at C side.
  Data m_data;

 this(int) {
   m_init(&this);
 }
 ~this() {
   m_free(&this);
 }
}

return CWrapper(0);
}

void main()
{
auto x = make_struct();
}

4) Please do not define free() function.


Re: Struct constructor, opCall mess.

2014-02-24 Thread Tobias Pankrath
On Tuesday, 25 February 2014 at 06:06:22 UTC, Jesse Phillips 
wrote:

On Monday, 24 February 2014 at 20:35:54 UTC, Remo wrote:
This looks like D2 is still in Beta stadium and not really 
ready for production use !?


If someone thinks that C++ was production ready in 1998, just go 
and try a C++ compiler from this time.


Re: Struct constructor, opCall mess.

2014-02-24 Thread Jesse Phillips

On Monday, 24 February 2014 at 20:35:54 UTC, Remo wrote:
This looks like D2 is still in Beta stadium and not really 
ready for production use !?


I believe it is ready for production, but you can't expect it to 
be ready in all cases. Mostly its lack of readiness isn't because 
of the language though. For example it isn't ready for production 
Android/iOS development, because it hasn't been done yet. It 
isn't ready for Epic to write Unreal 5 Engine in it. However if 
Valve believed in D I'd say it was ready for them to take on the 
challenge and write Source 2 in D.


Re: Struct constructor, opCall mess.

2014-02-24 Thread Jesse Phillips

On Monday, 24 February 2014 at 23:34:51 UTC, Remo wrote:

Where I can find more info about 'D's move semantics'?
Apparently it is not the same as rvalue reference and move 
semantics in C++11 ?


Here is the place I know of:
http://dconf.org/2013/talks/cehreli.html


Re: Struct constructor, opCall mess.

2014-02-24 Thread Remo

On Monday, 24 February 2014 at 21:06:03 UTC, monarch_dodra wrote:

On Monday, 24 February 2014 at 17:15:10 UTC, Remo wrote:
So what is proper/best way to mimic default constructor for 
struct ?


Honestly, you can't, and you shouldn't try either. There "used" 
to be the static opCall that allowed:


auto a = T();


But:
a) This is being phased out: If T has a constructor, it will 
seize to compile.
b) It's not "default": "T a;" will still compile, but not 
construct.


The feedback I've been getting is that the "correct" way to 
guarantee construction is to do it via a named factory pattern. 
You disable the this(), so as to "force" initialization, and 
make the constructors private. You'll get something along the 
lines of:


T a; //Nope.
T a = T(); //Nope
T a = T.build(); //OK!
T a = T(1, 2); //Nope!
T a = T.build(1, 2); //OK!
T a = T.init; //OK! Special explicit requrest for 
non-initialisation.


With D's move semantics and (N)RVO, there should be 0 overhead 
to do this.



Thanks, I will try to make this this way and look how well it 
will work.  But it could complicate connection from C++ to D and 
back.


Where I can find more info about 'D's move semantics'?
Apparently it is not the same as rvalue reference and move 
semantics in C++11 ?




Re: Struct constructor, opCall mess.

2014-02-24 Thread monarch_dodra

On Monday, 24 February 2014 at 17:15:10 UTC, Remo wrote:
So what is proper/best way to mimic default constructor for 
struct ?


Honestly, you can't, and you shouldn't try either. There "used" 
to be the static opCall that allowed:


auto a = T();


But:
a) This is being phased out: If T has a constructor, it will 
seize to compile.
b) It's not "default": "T a;" will still compile, but not 
construct.


The feedback I've been getting is that the "correct" way to 
guarantee construction is to do it via a named factory pattern. 
You disable the this(), so as to "force" initialization, and make 
the constructors private. You'll get something along the lines of:


T a; //Nope.
T a = T(); //Nope
T a = T.build(); //OK!
T a = T(1, 2); //Nope!
T a = T.build(1, 2); //OK!
T a = T.init; //OK! Special explicit requrest for 
non-initialisation.


With D's move semantics and (N)RVO, there should be 0 overhead to 
do this.


Re: Struct constructor, opCall mess.

2014-02-24 Thread Remo



Also please take a look at those:

https://d.puremagic.com/issues/show_bug.cgi?id=7066

There may be some others I've missed; the sheer amount and 
unresolved state is terrifying.


IMHO  Issue 7066 is not a bug but a feature.
Of course it could be handled i a bit more safe way.

This looks like D2 is still in Beta stadium and not really ready 
for production use !?


Re: Struct constructor, opCall mess.

2014-02-24 Thread Remo

Fortunately?
Yes I think it is. Of course it could be made a more safe in some 
way.


I think the big advantage of D is that it has 'bridge' to C and 
C++.

This way it appears to be easy to port some C++ code to D.
And it appears to be easy to interconnect C++ and D code. (via 
Dll for example)



@disable this()

Yes this is possible.
But then why it is not possible to use something like this ?
@default this();

For Vector example this works pretty well this way.
But my main problem is more complicated.

extern(C)  int init(ref CWrapper p);
extern(C) void free(ref CWrapper p);

struct CWrapper
{
  //some data that must be the same at C side.
  Data m_data;

  this() {
 init(&this);
  }
  ~this() {
 free(&this);
  }
}

How to do something like this in D ?
Using class appears for me to be wrong direction.


On Monday, 24 February 2014 at 18:13:02 UTC, Stanislav Blinov 
wrote:

On Monday, 24 February 2014 at 17:15:10 UTC, Remo wrote:

Well fortunately it seems to be possible to override init 
property.


Fortunately? I think not. It's an abomination that, IMO, has to 
be annihilated. Recently Andrei suggested adding more explicit 
semantics to .init that may give some leeway in this matter, 
although this was concerning classes and non-null default 
values, so it may not concern structs at all. Regardless, my 
advice - don't try to override .init, i.e. don't invite trouble 
into your code :)



But it still does not called at struct construction.
http://melpon.org/wandbox/permlink/9EvcdzKUKoufqbJa


Yup.

So what is proper/best way to mimic default constructor for 
struct ?


Don't do it. Default construction for struct *is* 
initialization of its fields.
If you want to do something other that initialize fields - 
create a function and call it explicitly. D is not C++, don't 
expect it to behave identically. To make it easier when porting 
code, you can always temporarily @disable this() so the 
compiler will stop whenever you'd use your "special" default 
construction in C++.


As you've mentioned, the code from your example doesn't need 
any special default constructors at all, this will work just 
fine:


struct Vector(T) {
T x = 0, y = 0, z = 0;

this(T v) { x = y = z = v; }
this(T x, T y, T z) { this.x = x; this.y = y; this.z = z; }
}


unittest {
Vector!double v;
auto v2 = Vector!double(1);
auto v3 = Vector!double(1,2,3);

assert(v.x == v.y && v.y == v.z && v.z == 0);
assert(v2.x == v2.x && v2.y == v2.z && v2.z == 1);
assert(v3.x == 1 && v3.y == 2 && v3.z == 3);
}


Also please take a look at those:

https://d.puremagic.com/issues/show_bug.cgi?id=3438
https://d.puremagic.com/issues/show_bug.cgi?id=6080
https://d.puremagic.com/issues/show_bug.cgi?id=7066
https://d.puremagic.com/issues/show_bug.cgi?id=7597
https://d.puremagic.com/issues/show_bug.cgi?id=8816
https://d.puremagic.com/issues/show_bug.cgi?id=8817
https://d.puremagic.com/issues/show_bug.cgi?id=10413
https://d.puremagic.com/issues/show_bug.cgi?id=11307

There may be some others I've missed; the sheer amount and 
unresolved state is terrifying.




Re: Struct constructor, opCall mess.

2014-02-24 Thread Stanislav Blinov

On Monday, 24 February 2014 at 17:15:10 UTC, Remo wrote:

Well fortunately it seems to be possible to override init 
property.


Fortunately? I think not. It's an abomination that, IMO, has to 
be annihilated. Recently Andrei suggested adding more explicit 
semantics to .init that may give some leeway in this matter, 
although this was concerning classes and non-null default values, 
so it may not concern structs at all. Regardless, my advice - 
don't try to override .init, i.e. don't invite trouble into your 
code :)



But it still does not called at struct construction.
http://melpon.org/wandbox/permlink/9EvcdzKUKoufqbJa


Yup.

So what is proper/best way to mimic default constructor for 
struct ?


Don't do it. Default construction for struct *is* initialization 
of its fields.
If you want to do something other that initialize fields - create 
a function and call it explicitly. D is not C++, don't expect it 
to behave identically. To make it easier when porting code, you 
can always temporarily @disable this() so the compiler will stop 
whenever you'd use your "special" default construction in C++.


As you've mentioned, the code from your example doesn't need any 
special default constructors at all, this will work just fine:


struct Vector(T) {
T x = 0, y = 0, z = 0;

this(T v) { x = y = z = v; }
this(T x, T y, T z) { this.x = x; this.y = y; this.z = z; }
}


unittest {
Vector!double v;
auto v2 = Vector!double(1);
auto v3 = Vector!double(1,2,3);

assert(v.x == v.y && v.y == v.z && v.z == 0);
assert(v2.x == v2.x && v2.y == v2.z && v2.z == 1);
assert(v3.x == 1 && v3.y == 2 && v3.z == 3);
}


Also please take a look at those:

https://d.puremagic.com/issues/show_bug.cgi?id=3438
https://d.puremagic.com/issues/show_bug.cgi?id=6080
https://d.puremagic.com/issues/show_bug.cgi?id=7066
https://d.puremagic.com/issues/show_bug.cgi?id=7597
https://d.puremagic.com/issues/show_bug.cgi?id=8816
https://d.puremagic.com/issues/show_bug.cgi?id=8817
https://d.puremagic.com/issues/show_bug.cgi?id=10413
https://d.puremagic.com/issues/show_bug.cgi?id=11307

There may be some others I've missed; the sheer amount and 
unresolved state is terrifying.


Re: Struct constructor, opCall mess.

2014-02-24 Thread Remo
On Monday, 24 February 2014 at 14:14:43 UTC, Tobias Pankrath 
wrote:

On Monday, 24 February 2014 at 13:56:01 UTC, Remo wrote:

Hi,

right now I am truing to figure out how the constructors 
behave in D2.


Question 1: why it is not possible to create custom ctor for 
struct?


The design of D relies on the fact that every type has a T.init 
property that is known to the compiler and used when in C++ the 
default ctor would get called. In constructors you can rely on 
(this == T.init), for example.


You need to pick one T.init or default constructors and D 
picked T.init.



Well fortunately it seems to be possible to override init 
property.

But it still does not called at struct construction.
http://melpon.org/wandbox/permlink/9EvcdzKUKoufqbJa

So what is proper/best way to mimic default constructor for 
struct ?




Re: Struct constructor, opCall mess.

2014-02-24 Thread Tobias Pankrath

On Monday, 24 February 2014 at 13:56:01 UTC, Remo wrote:

Hi,

right now I am truing to figure out how the constructors behave 
in D2.


Question 1: why it is not possible to create custom ctor for 
struct?


The design of D relies on the fact that every type has a T.init 
property that is known to the compiler and used when in C++ the 
default ctor would get called. In constructors you can rely on 
(this == T.init), for example.


You need to pick one T.init or default constructors and D picked 
T.init.




Struct constructor, opCall mess.

2014-02-24 Thread Remo

Hi,

right now I am truing to figure out how the constructors behave 
in D2.


Question 1: why it is not possible to create custom ctor for 
struct?
I know this is not really necessary because you can initialize 
fields like this.

struct S{ int i = 1; }

But this is a big problem if one tries to port C++ code to D2 and 
default ctor call some important initialization code.


Question 2: is there a way to mimic compiler generated ctor (that 
work in CTFE)?


Question 3: why it is possible to call static opCall like this?
VectorC v5 = v4(1.0);

Right now opCall seems to be better as this(...) because it work 
in CTFE but because of unwanted calls this is not well at all.


Question 4: why this(...) does not work in CTFE mode?

Here is highly simplified test code.
http://melpon.org/wandbox/permlink/ofvNby99mKqOBQBf

I am asking this because I am learning D2 now by porting and 
warping/connecting some big C++ (C++11) project to D2.