www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - alias this constructor

reply Dave Jones <dave jones.com> writes:
struct Foo
{
     int x;
     alias x this;
}

Foo f = 12; // error

Foo foo;
f = 12;     // this is OK

any reason why the first cant be allowed?
Mar 24 2018
next sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, March 25, 2018 00:47:20 Dave Jones via Digitalmars-d wrote:
 struct Foo
 {
      int x;
      alias x this;
 }

 Foo f = 12; // error

 Foo foo;
 f = 12;     // this is OK

 any reason why the first cant be allowed?
Because it was deemed to cause too many problems. C++ code can have quite a few problems related to all of the implicit conversions it allows with stuff like constructing objects. Walter decided that D would be better off if it did not allow such conversions, and as such, D is much pickier about implicit conversions in general. Occasionally, the restrictions are annoying, but they also prevent bugs. I have no idea whether Walter could be convinced at this point to allow some sort of implicit construction in D or not. Personally, I tend to think that we'd be better off if we didn't have alias this at all, because it tends to cause problems in anything outside of simple use cases (especially with generic code - implicit conversions in generic code are almost always a terrible idea). Sometimes, it's useful, but it's often just a recipe for subtle bugs. But at least the fact that D only allows you to implicitly convert in one direction reduces the problem. - Jonathan M Davis
Mar 24 2018
parent reply Shachar Shemesh <shachar weka.io> writes:
On 25/03/18 04:51, Jonathan M Davis wrote:
 On Sunday, March 25, 2018 00:47:20 Dave Jones via Digitalmars-d wrote:
 struct Foo
 {
       int x;
       alias x this;
 }

 Foo f = 12; // error

 Foo foo;
 f = 12;     // this is OK

 any reason why the first cant be allowed?
Because it was deemed to cause too many problems. C++ code can have quite a few problems related to all of the implicit conversions it allows with stuff like constructing objects. Walter decided that D would be better off if it did not allow such conversions, and as such, D is much pickier about implicit conversions in general.
That's a good reason to disallow assignment from int to Foo. I see zero sense in allowing assignment and disallowing construction. ***** Technically, I understand the mechanisms at play here. During construction, this is a Foo object, and it has no construction from int. During assignment, we are allowed to convert a Foo lvalue to a Foo.x (int) lvalue, and that gets assigned. Despite understanding the mechanics, I find the end result surprising and unexpected. D makes it damn easy to implicitly expose an inner member, and much more difficult to actually do this safely (you have to create a property and then alias this that property). If I'd be building C++ today, I'd replace the "explicit" keyword with "implicit" (i.e. - still allow single var constructors to become implicit conversion ops, but make that transformation an opt-in rather than an opt-out feature). I think that would have been a much better approach than what D took. Shachar
Mar 24 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, March 25, 2018 06:24:35 Shachar Shemesh via Digitalmars-d wrote:
 On 25/03/18 04:51, Jonathan M Davis wrote:
 On Sunday, March 25, 2018 00:47:20 Dave Jones via Digitalmars-d wrote:
 struct Foo
 {

       int x;
       alias x this;

 }

 Foo f = 12; // error

 Foo foo;
 f = 12;     // this is OK

 any reason why the first cant be allowed?
Because it was deemed to cause too many problems. C++ code can have quite a few problems related to all of the implicit conversions it allows with stuff like constructing objects. Walter decided that D would be better off if it did not allow such conversions, and as such, D is much pickier about implicit conversions in general.
That's a good reason to disallow assignment from int to Foo. I see zero sense in allowing assignment and disallowing construction. ***** Technically, I understand the mechanisms at play here. During construction, this is a Foo object, and it has no construction from int. During assignment, we are allowed to convert a Foo lvalue to a Foo.x (int) lvalue, and that gets assigned. Despite understanding the mechanics, I find the end result surprising and unexpected. D makes it damn easy to implicitly expose an inner member, and much more difficult to actually do this safely (you have to create a property and then alias this that property).
Having something like opImplicitCast would arguably have been better than alias this.
 If I'd be building C++ today, I'd replace the "explicit" keyword with
 "implicit" (i.e. - still allow single var constructors to become
 implicit conversion ops, but make that transformation an opt-in rather
 than an opt-out feature). I think that would have been a much better
 approach than what D took.
That would be a significant improvement for C++, though over time, I've increasingly become of the opinion that adding implicit conversions to user-defined types is more trouble than it's worth. There are certainly times when it's useful, but it causes enough problems that I'm not at all convinced that it's ultimately a feature worth having. And with the route that D went, implicit conversions are arguably crippled anyway. So, we have a partial solution that isn't really enough to cleanly use implicit conversions when it might be appropriate, but what we have is still enough to cause problems. - Jonathan M Davis
Mar 24 2018
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 25 March 2018 at 00:47:20 UTC, Dave Jones wrote:
 struct Foo
 {
     int x;
     alias x this;
 }

 Foo f = 12; // error
You just need to define a constructor that takes an int. alias this is all about taking an existing object and substituting a member for it - emphasis on *existing* object, so it needs to already be constructed. But you can construct from other types struct Foo { int x; this(int x) { this.x = x; } } Foo f = 12; // allowed, calls that constructor
 Foo foo;
 f = 12;     // this is OK
Important to note that foo already exists here and is NOT reconstructed - the compiler just rewrites that into `f.x = 12;`, doing a member assignment.
Mar 24 2018