www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Postblit not invokable with MyStruct(MyStruct()); ?

reply "Mark Isaacson" <turck11 hotmail.com> writes:
I have just discovered that the postblit constructor is not able 
to be invoked like a "normal" constructor, or, as one would 
manually do so in C++ with a copy constructor. Accordingly I have 
a couple questions:

1) What are the various ways to invoke the postblit constructor? 
I have not tested, but assume that:

auto s1 = MyStruct();
auto s2 = s1;

Is one such way to invoke it and that:

auto s1 = MyStruct;
foo(s1);

Where foo is defined as: void foo(MyStruct s) {}

is another way. Are there others?


2) I ran into this issue while attempting to leverage the 
postblit for code-reuse. In particular, I have a setup that is 
similar to:

struct A {
   this(B b) { /* Stuff */ }
}

struct B {

}

void foo(T)(T param) {
   auto a = A(param);
   /* Stuff */
}

unittest {
   foo(A()); //Fails
   foo(B()); //Succeeds
}

The notion being that A and B are 2 ways to represent the same 
thing, why not convert everything to the A format and proceed 
from there; I figured the compiler would optimize out the 
pointless copy when T == A. Alas, as shown in my unittest, foo 
fails to accept arguments of type A.

I suppose my question would be: What is the idiomatic way of 
accomplishing this form of code reuse in D?

I'd prefer to not have to write two versions of foo, even if one 
is as simple as converting the argument and passing it to the 
other. I'd also prefer to avoid having some shenangians along the 
lines of:

void foo(T)(T param) {
   static if (is(T == A)) {
     auto a = param;
   } else {
     auto a = A(param);
   }
}

As this would be difficult to express in a template constraint in 
the function signature.
May 02 2014
next sibling parent reply "Mark Isaacson" <turck11 hotmail.com> writes:
Did some thinking: Realized that the appropriate mechanism to 
express that A and B are two ways of representing the same thing 
is to do so via opCast. I had not considered this option 
carefully initially as I am translating someone else's C++ code 
to D and hoped that they had used the appropriate representations 
on the C++ side.

I added the appropriate code to permit casting and I was then 
able to get the desired code-reuse and template constraints.

Accordingly, I no longer need an answer to my second question 
unless someone knows of a more idiomatic way to get the same 
results.
May 02 2014
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Mark Isaacson:

 Accordingly, I no longer need an answer to my second question 
 unless someone knows of a more idiomatic way to get the same 
 results.
Is the "alias this" useful in this case? Bye, bearophile
May 02 2014
parent "Mark Isaacson" <turck11 hotmail.com> writes:
 bearophile - Unless I'm missing something, alas, no. Neither A 
nor B is a subtype of the other. In particular, in the real code 
one is a CartesianVector and the other a PolarVector. For what 
it's worth, 'foo' is actually opBinary addition.

Thanks for the thought though.
May 02 2014
prev sibling parent reply Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On 05/03/14 01:05, Mark Isaacson via Digitalmars-d-learn wrote:
 2) I ran into this issue while attempting to leverage the postblit for
code-reuse. In particular, I have a setup that is similar to:
 
 struct A {
   this(B b) { /* Stuff */ }
 }
 
 struct B {
 }
 
 void foo(T)(T param) {
   auto a = A(param);
   /* Stuff */
 }
 
 unittest {
   foo(A()); //Fails
   foo(B()); //Succeeds
 }
 
 The notion being that A and B are 2 ways to represent the same thing, why not
convert everything to the A format and proceed from there; I figured the
compiler would optimize out the pointless copy when T == A. Alas, as shown in
my unittest, foo fails to accept arguments of type A.
What actually fails is the initialization of 'a'. Add another this(A a) { /* Stuff */ } constructor to the 'A' struct, and it will work. And, yes, the missing cpctors are a language problem. artur
May 03 2014
parent "Mark Isaacson" <turck11 hotmail.com> writes:
 What actually fails is the initialization of 'a'.
 Add another

    this(A a) { /* Stuff */ }

 constructor to the 'A' struct, and it will work.


 And, yes, the missing cpctors are a language problem.

 artur
Thanks. Yeah, I figured I could do that, I was just hoping that I could leverage the postblit. Ultimately my answer to my second question became: "Calling the postblit directly is far too low level, just use std.conv.to instead". to!A(x) did exactly the right thing (without any modification of the original classes I think).
May 03 2014