www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Special Type Challenge

reply "Jonathan Marler" <johnnymarler gmail.com> writes:
I'm wondering if the following is possible in D.  I tried and 
failed but maybe someone else will be able to pull it off.

// Challenge: Create a type named "Byte" that,
//   1. Uses 1 byte of memory
//   2. Can be used as an argument to a non-template function
//   3. Handles implicit conversion from any 1-byte type
//   4. Compiles and passes the following unittest
unittest
{
   Byte b;

   b = 0;
   b = 1;
   b = 255;
   b = -256;

   b = 'a';
   b = cast(const char)'a';
   b = cast(immutable char)'a';
   b = cast(byte)1;
   b = cast(const byte)1;
   b = cast(immutable byte)1;
   b = cast(ubyte)1;
   b = cast(const ubyte)1;
   b = cast(immutable ubyte)1;

   Byte echo(Byte b)
   {
     return b;
   }
   b = echo('a');
   b = echo(cast(const char)'a');
   b = echo(cast(immutable char)'a');
   b = echo(cast(byte)1);
   b = echo(cast(const byte)1);
   b = echo(cast(immutable byte)1);
   b = echo(cast(ubyte)1);
   b = echo(cast(const ubyte)1);
   b = echo(cast(immutable ubyte)1);

   Byte[] barr;

   barr = "teststring";
   barr = [0,1,2,3];
}
Feb 06 2015
next sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Saturday, 7 February 2015 at 01:55:27 UTC, Jonathan Marler 
wrote:
   Byte b;

   b = 0;
   b = 1;
   b = 255;
   b = -256;

   b = 'a';
   b = cast(const char)'a';
   b = cast(immutable char)'a';
   b = cast(byte)1;
   b = cast(const byte)1;
   b = cast(immutable byte)1;
   b = cast(ubyte)1;
   b = cast(const ubyte)1;
   b = cast(immutable ubyte)1;
These are possible with opAssign (which should be accompanied with corresponding constructor(s)).
   Byte echo(Byte b)
   {
     return b;
   }
   b = echo('a');
   b = echo(cast(const char)'a');
   b = echo(cast(immutable char)'a');
   b = echo(cast(byte)1);
   b = echo(cast(const byte)1);
   b = echo(cast(immutable byte)1);
   b = echo(cast(ubyte)1);
   b = echo(cast(const ubyte)1);
   b = echo(cast(immutable ubyte)1);

   Byte[] barr;

   barr = "teststring";
   barr = [0,1,2,3];
 }
These are not possible as D does not support implicit construction.
Feb 06 2015
parent "Jonathan Marler" <johnnymarler gmail.com> writes:
On Saturday, 7 February 2015 at 02:12:08 UTC, Jakob Ovrum wrote:
  Byte echo(Byte b)
  {
    return b;
  }
  b = echo('a');
  b = echo(cast(const char)'a');
  b = echo(cast(immutable char)'a');
  b = echo(cast(byte)1);
  b = echo(cast(const byte)1);
  b = echo(cast(immutable byte)1);
  b = echo(cast(ubyte)1);
  b = echo(cast(const ubyte)1);
  b = echo(cast(immutable ubyte)1);

  Byte[] barr;

  barr = "teststring";
  barr = [0,1,2,3];
 }
These are not possible as D does not support implicit construction.
It's a bit odd that D supports implicit conversions from user-defined types to built-in types but not the reverse. What's the reason for this? Is it done on purpose or is this just a hole that might be filled in later?
Feb 06 2015
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 7 February 2015 at 01:55:27 UTC, Jonathan Marler 
wrote:
   b = -256;
that won't fit in a byte btw. The rest of the assignment stuff is easy. I'd prolly even do it with a template: this(T)(T t) { this.opAssign(t); } // for construction Byte opAssign(T)(T t) if(T.sizeof == 1) { // for other assignment data_holder = cast(typeof(data_holder) t); } and that should do it.
   Byte[] barr;

   barr = "teststring";
   barr = [0,1,2,3];
 }
Language won't let you do these though.
Feb 06 2015
parent reply "Jonathan Marler" <johnnymarler gmail.com> writes:
On Saturday, 7 February 2015 at 03:48:24 UTC, Adam D. Ruppe wrote:
 wrote:
  b = -256;
that won't fit in a byte btw.
Woops, I typed that example too fast :)
 The rest of the assignment stuff is easy. I'd prolly even do it 
 with a template:

 this(T)(T t) { this.opAssign(t); } // for construction
 Byte opAssign(T)(T t) if(T.sizeof == 1) { // for other 
 assignment
     data_holder = cast(typeof(data_holder) t);
 }

 and that should do it.
This code is almost exactly what I came up with. But what about the function problem? void echo(Byte b); echo('c'); // won't work I can't figure out a way to make this work (without making echo a template). If D supported implicit conversions from built-in types to user types then it could work. Do you know if D might support that later or if there's a reason for not supporting it?
Feb 06 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/6/15 8:28 PM, Jonathan Marler wrote:
 Do you know if D might support that later or if there's a reason for not
 supporting it?
It's deliberate following the C++ experience. -- Andrei
Feb 06 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 7 February 2015 at 05:27:39 UTC, Andrei Alexandrescu 
wrote:
 On 2/6/15 8:28 PM, Jonathan Marler wrote:
 Do you know if D might support that later or if there's a 
 reason for not
 supporting it?
It's deliberate following the C++ experience. -- Andrei
Hasn't there been a debate about a hypothetical `opImplicitCast()`? The default would still be off, but you can opt-in by defining said method.
Feb 07 2015
next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Saturday, 7 February 2015 at 19:38:10 UTC, Marc Schütz wrote:
 On Saturday, 7 February 2015 at 05:27:39 UTC, Andrei 
 Alexandrescu wrote:
 On 2/6/15 8:28 PM, Jonathan Marler wrote:
 Do you know if D might support that later or if there's a 
 reason for not
 supporting it?
It's deliberate following the C++ experience. -- Andrei
Hasn't there been a debate about a hypothetical `opImplicitCast()`? The default would still be off, but you can opt-in by defining said method.
`alias this` is pretty much `opImplicitCast`, but it currently has a few holes, such as http://forum.dlang.org/post/xcnwuneclebuyqcjbkwu forum.dlang.org. It's not always appropriate in every situation though, as you get full-on subtyping along with implicit conversion.
Feb 07 2015
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 7 February 2015 at 20:53:48 UTC, Meta wrote:
 On Saturday, 7 February 2015 at 19:38:10 UTC, Marc Schütz wrote:
 On Saturday, 7 February 2015 at 05:27:39 UTC, Andrei 
 Alexandrescu wrote:
 On 2/6/15 8:28 PM, Jonathan Marler wrote:
 Do you know if D might support that later or if there's a 
 reason for not
 supporting it?
It's deliberate following the C++ experience. -- Andrei
Hasn't there been a debate about a hypothetical `opImplicitCast()`? The default would still be off, but you can opt-in by defining said method.
`alias this` is pretty much `opImplicitCast`, but it currently has a few holes, such as http://forum.dlang.org/post/xcnwuneclebuyqcjbkwu forum.dlang.org. It's not always appropriate in every situation though, as you get full-on subtyping along with implicit conversion.
No, `alias this` convert from the type it is declared in to another type. `opImplicitCast` would be declared in the destination type.
Feb 08 2015
parent reply "Meta" <jared771 gmail.com> writes:
On Sunday, 8 February 2015 at 13:06:08 UTC, Marc Schütz wrote:
 No, `alias this` convert from the type it is declared in to 
 another type. `opImplicitCast` would be declared in the 
 destination type.
So like this? struct Type1 { string str; } struct Type2 { string str; Type2 opImplicitCast(Type1 t) { return Type2(t.str); } } void main() { Type2 t2 = Type1("Hello, World!"); } Instead of the opposite?
Feb 08 2015
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Sunday, 8 February 2015 at 19:59:40 UTC, Meta wrote:
 On Sunday, 8 February 2015 at 13:06:08 UTC, Marc Schütz wrote:
 No, `alias this` convert from the type it is declared in to 
 another type. `opImplicitCast` would be declared in the 
 destination type.
So like this? struct Type1 { string str; } struct Type2 { string str; Type2 opImplicitCast(Type1 t) { return Type2(t.str); } } void main() { Type2 t2 = Type1("Hello, World!"); } Instead of the opposite?
Yes. It's almost like a constructor, but would be called wherever an explicit call to the constructor is required today: struct S { this(int x) {} } S test1() { return 10; // not ok return S(10); // works } struct T { static typeof(this) opImplicitCast(int x) { return typeof(this)(x); } } T test1() { return 10; // ok return T(10); // not sure whether this should // work or not } Because it's so similar to a constructor (it always needs to be static and return `typeof(this)`), maybe a special syntax can be used: struct S { implicit this(int x) {} }
Feb 09 2015
prev sibling parent "Tofu Ninja" <emmons0 purdue.edu> writes:
On Saturday, 7 February 2015 at 19:38:10 UTC, Marc Schütz wrote:
 Hasn't there been a debate about a hypothetical 
 `opImplicitCast()`? The default would still be off, but you can 
 opt-in by defining said method.
How else would it be done? I am still confused as to what the reasons behind not having implicit conversion are.
Feb 07 2015