www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How made my to!MyStruct

reply Zardoz <luis.panadero gmail.com> writes:
Hi. I made a parametrized struct, a Vector, and I'm trying to make to! work to
make conversion between Vectors with
different parametrized type.

Code :

public struct Vector(T, size_t dim_)
if (__traits(isFloating, T) ) {
  static enum size_t dim = dim_; /// Vector Dimension

  static assert (dim >= 2 && dim <= 4, "Not valid dimension size.");
  static assert (__traits(isFloating, T), "Type not is a Float Point type.");
// Ok, redundant
  static assert (is(T : real), "Type not is like a Float Point type.");

  union {
    private T[dim] coor; /// Vector coords like Array

    struct {
      static if( dim >= 1) T x;
      static if( dim >= 2) T y;
      static if( dim >= 3) T z;
      static if( dim >= 4) T w;
    }
  }
  // Constructors and other methods/stuff....
}

Actually I saw std.conv code and I see that to! call to a parametrized funtion
called toImpl(T,S) (S s).
I made my own toImpl for convert a Vector to another Vector and I checked that
it works calling directly :
/**
* to converto a vector to other vector
*/
T toImpl(T, S)(S s)
if (!implicitlyConverts!(S, T) && isVector!T && isVector!S )
{
  static assert (T.dim >= S.dim, "Original Vector bigger that destiny Vector");
  T newVector; auto i = 0;
  static if (is (typeof(newVector.x) == typeof(s.x)))  {
    for (; i < S.dim; i++)
      newVector.coor[i] =  s.coor[i];
  } else {
    for (; i < S.dim; i++)
      newVector.coor[i] =  to!(typeof(newVector.x))(s.coor[i]);
  }

  for (; i< T.dim; i++) // Expands a small vector to a bigger dimension with 0
value in extra dimension
    newVector.coor[i] = 0;

  return newVector;
}

But when I try to use to! (for example to!Vector(double, 4) (other_Vector)), I
get a error from srd.conv :

/usr/include/d/dmd/phobos/std/conv.d(99): Error: template std.conv.toImpl(T,S)
if (!implicitlyConverts!(S,T) &&
isSomeString!(T) && isInputRange!(Unqual!(S)) && isSomeChar!(ElementType!(S)))
does not match any function template
declaration
/usr/include/d/dmd/phobos/std/conv.d(99): Error: template std.conv.toImpl(T,S)
if (!implicitlyConverts!(S,T) &&
isSomeString!(T) && isInputRange!(Unqual!(S)) && isSomeChar!(ElementType!(S)))
cannot deduce template function from
argument types !(Vector!(double,4))(Vector!(float,2))
/usr/include/d/dmd/phobos/std/conv.d(99): Error: template instance errors
instantiating template
src/vector.d(139): Error: template instance
std.conv.to!(Vector!(double,4)).to!(Vector!(float,2)) error instantiating

What I'm doing wrong ???
Jun 25 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-25 11:09, Zardoz wrote:
 Hi. I made a parametrized struct, a Vector, and I'm trying to make to! work
 to make conversion between Vectors with different parametrized type.
 
 Code :
 
 public struct Vector(T, size_t dim_)
 if (__traits(isFloating, T) ) {
   static enum size_t dim = dim_; /// Vector Dimension
 
   static assert (dim >= 2 && dim <= 4, "Not valid dimension size.");
   static assert (__traits(isFloating, T), "Type not is a Float Point
 type."); // Ok, redundant static assert (is(T : real), "Type not is like a
 Float Point type.");
 
   union {
     private T[dim] coor; /// Vector coords like Array
 
     struct {
       static if( dim >= 1) T x;
       static if( dim >= 2) T y;
       static if( dim >= 3) T z;
       static if( dim >= 4) T w;
     }
   }
   // Constructors and other methods/stuff....
 }
 
 Actually I saw std.conv code and I see that to! call to a parametrized
 funtion called toImpl(T,S) (S s). I made my own toImpl for convert a
 Vector to another Vector and I checked that it works calling directly :
 /**
 * to converto a vector to other vector
 */
 T toImpl(T, S)(S s)
 if (!implicitlyConverts!(S, T) && isVector!T && isVector!S )
 {
   static assert (T.dim >= S.dim, "Original Vector bigger that destiny
 Vector"); T newVector; auto i = 0;
   static if (is (typeof(newVector.x) == typeof(s.x)))  {
     for (; i < S.dim; i++)
       newVector.coor[i] =  s.coor[i];
   } else {
     for (; i < S.dim; i++)
       newVector.coor[i] =  to!(typeof(newVector.x))(s.coor[i]);
   }
 
   for (; i< T.dim; i++) // Expands a small vector to a bigger dimension
 with 0 value in extra dimension newVector.coor[i] = 0;
 
   return newVector;
 }
 
 But when I try to use to! (for example to!Vector(double, 4)
 (other_Vector)), I get a error from srd.conv :
 
 /usr/include/d/dmd/phobos/std/conv.d(99): Error: template
 std.conv.toImpl(T,S) if (!implicitlyConverts!(S,T) && isSomeString!(T) &&
 isInputRange!(Unqual!(S)) && isSomeChar!(ElementType!(S))) does not match
 any function template declaration
 /usr/include/d/dmd/phobos/std/conv.d(99): Error: template
 std.conv.toImpl(T,S) if (!implicitlyConverts!(S,T) && isSomeString!(T) &&
 isInputRange!(Unqual!(S)) && isSomeChar!(ElementType!(S))) cannot deduce
 template function from argument types
 !(Vector!(double,4))(Vector!(float,2))
 /usr/include/d/dmd/phobos/std/conv.d(99): Error: template instance errors
 instantiating template src/vector.d(139): Error: template instance
 std.conv.to!(Vector!(double,4)).to!(Vector!(float,2)) error instantiating
 
 What I'm doing wrong ???

std.conv.to does not currently work to convert between user-defined types. There has been some discussion about making it work for such cases, and there's currently a pull request on github that deals with it, so it may be possible to convert between user-defined types with std.conv.to in the next release, but you can't currently do it. - Jonathan M Davis
Jun 25 2011
prev sibling parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Zardoz Wrote:

 Hi. I made a parametrized struct, a Vector, and I'm trying to make to! work to
make conversion between Vectors with
 different parametrized type.

You should be able to override opCast and have it work with std.to, or I believe that is intended to work.
Jun 25 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-25 14:45, Jesse Phillips wrote:
 Zardoz Wrote:
 Hi. I made a parametrized struct, a Vector, and I'm trying to make to!
 work to make conversion between Vectors with different parametrized
 type.

You should be able to override opCast and have it work with std.to, or I believe that is intended to work.

Nope. It won't work. It'll probably work with the next release, but it won't work right now. You can use std.conv.to instead of a cost for converting between derived objects; you can use it to convert an object to a string using its toString function; and if you have a to function on your struct or class which converts to a primitive type, you can use that with std.conv.to. But you can't currently convert between two unrelated objects using std.conv.to, even if they have the appropriate opCasts or constructors. That should change soon, but for now, we're out of luck. - Jonathan M Davis
Jun 25 2011
prev sibling parent Zardoz <luis.panadero gmail.com> writes:
On Sat, 25 Jun 2011 15:32:40 -0700, Jonathan M Davis wrote:

 On 2011-06-25 14:45, Jesse Phillips wrote:
 Zardoz Wrote:
 Hi. I made a parametrized struct, a Vector, and I'm trying to make
 to! work to make conversion between Vectors with different
 parametrized type.

You should be able to override opCast and have it work with std.to, or I believe that is intended to work.

Nope. It won't work. It'll probably work with the next release, but it won't work right now. You can use std.conv.to instead of a cost for converting between derived objects; you can use it to convert an object to a string using its toString function; and if you have a to function on your struct or class which converts to a primitive type, you can use that with std.conv.to. But you can't currently convert between two unrelated objects using std.conv.to, even if they have the appropriate opCasts or constructors. That should change soon, but for now, we're out of luck. - Jonathan M Davis

Yep, I try with opCast and to! not works yet. At least, I can do now, things like : auto v2d = Vector!(doble, 2) (1, 1); auto v = cast(Vector!(float, 4)) v2d; assert (v[0] == 1); assert (v[1] == 1); assert (v[2] == 0); assert (v[3] == 0); PD: Yep, I'm learning making a small lib to work with Vectors, Quaternions and squared Matrix... -- Yep, I'm afraid that I have a blog : zardoz.es
Jun 25 2011