Thread overview
Is there an equivavlent to C# boxing in D?
Feb 12, 2022
IGotD-
Feb 12, 2022
H. S. Teoh
Feb 12, 2022
IGotD-
Feb 12, 2022
H. S. Teoh
Feb 12, 2022
Basile B.
Feb 12, 2022
Ali Çehreli
February 12, 2022

If you want to store a value type on the heap in D you just use "new" and a pointer to the type. The same thing in C# would be to wrap the value type into an object. However when you do that automatic conversion without a cast seems not to be possible (C# also have a dynamic type that might solve that but more heavy weight).

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing

Is there a possibility to wrap a value type in D around the base object class that is otherwise used as the class reference type? Would this be a way to use D without raw pointers for heap allocated value types?

February 11, 2022
On Sat, Feb 12, 2022 at 12:27:34AM +0000, IGotD- via Digitalmars-d-learn wrote:
> If you want to store a value type on the heap in D you just use "new" and a pointer to the type. The same thing in C# would be to wrap the value type into an object. However when you do that automatic conversion without a cast seems not to be possible (C# also have a dynamic type that might solve that but more heavy weight).
> 
> https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing
> 
> Is there a possibility to wrap a value type in D around the base object class that is otherwise used as the class reference type? Would this be a way to use D without raw pointers for heap allocated value types?

How about this?

--------
final class Boxed(T) {
	T payload;
	alias payload this; // caveat: probably not a good idea in general
	this(T val) { payload = val; }
}

Boxed!int i = new Boxed!int(123);
int j = i; // hooray, implicit unboxing!
i = 321; // even this works
--------


T

-- 
Computers aren't intelligent; they only think they are.
February 12, 2022
On Saturday, 12 February 2022 at 00:41:22 UTC, H. S. Teoh wrote:
>
> How about this?
>
> --------
> final class Boxed(T) {
> 	T payload;
> 	alias payload this; // caveat: probably not a good idea in general
> 	this(T val) { payload = val; }
> }
>
> Boxed!int i = new Boxed!int(123);
> int j = i; // hooray, implicit unboxing!
> i = 321; // even this works
> --------
>

Pretty neat solution, you need an extra type but that's not much. If alias this would be removed in D, would tricks like these suddenly become impossible?


February 12, 2022
On Sat, Feb 12, 2022 at 09:37:56AM +0000, IGotD- via Digitalmars-d-learn wrote:
> On Saturday, 12 February 2022 at 00:41:22 UTC, H. S. Teoh wrote:
[...]
> > --------
> > final class Boxed(T) {
> > 	T payload;
> > 	alias payload this; // caveat: probably not a good idea in general
> > 	this(T val) { payload = val; }
> > }
> > 
> > Boxed!int i = new Boxed!int(123);
> > int j = i; // hooray, implicit unboxing!
> > i = 321; // even this works
> > --------
[...]
> Pretty neat solution, you need an extra type but that's not much. If alias this would be removed in D, would tricks like these suddenly become impossible?
[...]

Without alias this it would be harder to pull off, yes.  So this particular use case would constitute an example of classes + alias this not being an anti-pattern. (Unless one were to concede that boxed types in general are an anti-pattern... which I'm somewhat inclined to agree with, but I won't press that point. :-P)


T

-- 
Having a smoking section in a restaurant is like having a peeing section in a swimming pool. -- Edward Burr
February 12, 2022
On Saturday, 12 February 2022 at 16:50:16 UTC, H. S. Teoh wrote:
> Without alias this it would be harder to pull off, yes.

I don't see any other way that allows to unbox *implictly*.
That would require a new operator. Something like opCast but more permissive, that works without `cast`.


February 12, 2022
On 2/11/22 16:41, H. S. Teoh wrote:

> How about this?
>
> --------
> final class Boxed(T) {
> 	T payload;
> 	alias payload this; // caveat: probably not a good idea in general
> 	this(T val) { payload = val; }
> }
>
> Boxed!int i = new Boxed!int(123);
> int j = i; // hooray, implicit unboxing!
> i = 321; // even this works
> --------

I can't resist adding the convenience function. :)

auto boxed(T)(T val) {
  return new Boxed!T(val);
}

void main() {
  // Sweet:
  auto a = boxed(123);

  // Sweet too:
  auto b = 456.boxed;
}

Ali