Template type reduction

2016-08-15 Thread Engine Machine via Digitalmars-d-learn

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any T,

struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime 
inheritance, but at the compile time level.


I do not want to have to cast to S!T every time just to access x, 
e.g.,


struct Q
{
   Object s;
}

which is too general as s can be things that are not of type S!*.


Is this possible?



Re: Template type reduction

2016-08-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/15/16 3:31 PM, Engine Machine wrote:

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any T,

struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime inheritance, but
at the compile time level.


I don't think so. You'd have to cast, as the compiler doesn't have any 
understanding that all S instantiations will have an x member.



I do not want to have to cast to S!T every time just to access x, e.g.,

struct Q
{
   Object s;
}

which is too general as s can be things that are not of type S!*.


This seems odd. You will lose the type information for s if you were to 
succeed. Might as well just store an int.


Seems like what you want is a variant or some other kind of tagged union.

-Steve


Re: Template type reduction

2016-08-15 Thread Engine Machine via Digitalmars-d-learn
On Monday, 15 August 2016 at 19:40:37 UTC, Steven Schveighoffer 
wrote:

On 8/15/16 3:31 PM, Engine Machine wrote:

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any 
T,


struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime 
inheritance, but

at the compile time level.


I don't think so. You'd have to cast, as the compiler doesn't 
have any understanding that all S instantiations will have an x 
member.


This is a problem. How can I cast to something I don't know?



I do not want to have to cast to S!T every time just to access 
x, e.g.,


struct Q
{
   Object s;
}

which is too general as s can be things that are not of type 
S!*.


This seems odd. You will lose the type information for s if you 
were to succeed. Might as well just store an int.


Seems like what you want is a variant or some other kind of 
tagged union.


No, what I want is a type that is the intersection of all the 
types it can be.


The problem is I cannot cast because the type is complex and I 
don't know the exact signature, but I do know that it has a basic 
type embedded in it.


enum Types
{
   Int, Word, Complex
}

struct MyType(string name, Types type, Args...)
{
string Name = name;
Types Type = type;
static if (type == Int) int val;
static if (type == word) ushort val;
static if (type == Complex) { ... };
}


So, how can I get val? I know if it is an int or a word, val 
exists. But I can't specify the name or type at runtime to get at 
the innards of the type.


Object o = MyType!("test", Types.Int);

Useless! I can never retrieve anything from o. I can't cast it 
back. Yet I know that o has a name and a type and possibly a val 
if I know the type... and I know all this at compile time. Yet D 
doesn't seem to allow me to use this information.


I know one will say use either oop or constructors, but neither 
of these are appropriate(although constructors are close). What I 
need is a type constructor, which bridges the gap. This is how I 
am using the data above, to construct the object, but D treats it 
as part of the type, which I don't what.


I guess I will have to use string mixins to construct the types 
properly ;/ What a pain in the ass ;/








Re: Template type reduction

2016-08-16 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/16/16 12:33 AM, Engine Machine wrote:

On Monday, 15 August 2016 at 19:40:37 UTC, Steven Schveighoffer wrote:

On 8/15/16 3:31 PM, Engine Machine wrote:

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any T,

struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime inheritance, but
at the compile time level.


I don't think so. You'd have to cast, as the compiler doesn't have any
understanding that all S instantiations will have an x member.


This is a problem. How can I cast to something I don't know?


First, you have to store it somehow. I don't really know the way you can 
do this without a union or a Variant.


Then you can cast it to any concrete version of S, they all have an x 
member.





I do not want to have to cast to S!T every time just to access x, e.g.,

struct Q
{
   Object s;
}

which is too general as s can be things that are not of type S!*.


This seems odd. You will lose the type information for s if you were
to succeed. Might as well just store an int.



Seems like what you want is a variant or some other kind of tagged union.


No, what I want is a type that is the intersection of all the types it
can be.


Then you want std.variant.Variant. That's the only type that can change 
types at runtime.



The problem is I cannot cast because the type is complex and I don't
know the exact signature, but I do know that it has a basic type
embedded in it.

enum Types
{
   Int, Word, Complex
}

struct MyType(string name, Types type, Args...)
{
string Name = name;
Types Type = type;
static if (type == Int) int val;
static if (type == word) ushort val;
static if (type == Complex) { ... };
}


So, how can I get val? I know if it is an int or a word, val exists. But
I can't specify the name or type at runtime to get at the innards of the
type.


You need to know the type. Otherwise, how will the compiler be able to 
reserve enough space for it? Variant works by having enough space to 
store most things, and then boxes if it gets bigger.


With Variant, you can type stored at runtime.



Object o = MyType!("test", Types.Int);


Note that structs are not Objects. There is no base type for structs.


Useless! I can never retrieve anything from o. I can't cast it back. Yet
I know that o has a name and a type and possibly a val if I know the
type... and I know all this at compile time. Yet D doesn't seem to allow
me to use this information.

I know one will say use either oop or constructors, but neither of these
are appropriate(although constructors are close). What I need is a type
constructor, which bridges the gap. This is how I am using the data
above, to construct the object, but D treats it as part of the type,
which I don't what.


In D, structs are not inheritable. You really do need polymorphism for 
this. I don't know you reason for rejecting classes, but I would 
recommend that. Or use Variant.


-Steve


Re: Template type reduction

2016-08-16 Thread Lodovico Giaretta via Digitalmars-d-learn

On Monday, 15 August 2016 at 19:31:14 UTC, Engine Machine wrote:

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any T,

struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime 
inheritance, but at the compile time level.


I do not want to have to cast to S!T every time just to access 
x, e.g.,


struct Q
{
   Object s;
}

which is too general as s can be things that are not of type 
S!*.



Is this possible?


I don't know if this is exactly what you want:

=
import std.traits: hasMember;

struct Q(T)
if (hasMember!(T, "x"))
{
T s;

@property auto x() { return s.x; }
}
auto makeQ(T)(auto ref T val)
{
return Q!T(val);
}

auto s = myTypeWithFieldX();
auto q = makeQ(s);
assert(q.x == s.x);
=

`Q` can store any type with an `x` field and gives access to it. 
The auxiliary function `makeQ` acts as a constructor for `Q` with 
template parameter deduction.


Re: Template type reduction

2016-08-16 Thread Engine Machine via Digitalmars-d-learn
On Tuesday, 16 August 2016 at 17:39:14 UTC, Lodovico Giaretta 
wrote:

On Monday, 15 August 2016 at 19:31:14 UTC, Engine Machine wrote:

Suppose I have a templated type like

struct S(T) { int x; static if (T is Y) int y; }

I would like to be able to create a reference to S(T) for any 
T,


struct Q
{
  S!* s; // Can hold any type of S.
}

and be able to access s.x, since it is common to all S.

Can D do anything like this? It is sort of like runtime 
inheritance, but at the compile time level.


I do not want to have to cast to S!T every time just to access 
x, e.g.,


struct Q
{
   Object s;
}

which is too general as s can be things that are not of type 
S!*.



Is this possible?


I don't know if this is exactly what you want:

=
import std.traits: hasMember;

struct Q(T)
if (hasMember!(T, "x"))
{
T s;

@property auto x() { return s.x; }
}
auto makeQ(T)(auto ref T val)
{
return Q!T(val);
}

auto s = myTypeWithFieldX();
auto q = makeQ(s);
assert(q.x == s.x);
=

`Q` can store any type with an `x` field and gives access to 
it. The auxiliary function `makeQ` acts as a constructor for 
`Q` with template parameter deduction.


The only problem is Q is still defined by T. Your makeQ then 
requires the type implicitly, which I don't necessarily have. 
You've simply added complexity to the problem but the issue is 
still there.


I realize now that D simply cannot do what I ask directly because 
It's type parameters are part of the type. It can't be told that 
in some cases they are not. Any use of the parameters, as I am 
using them, will result in this issue.


I'm now trying a different method which builds the based types 
using partial oop and partial CT code. The CT code is only for 
performance and convenience anyways.







Re: Template type reduction

2016-08-16 Thread Lodovico Giaretta via Digitalmars-d-learn

On Tuesday, 16 August 2016 at 19:23:51 UTC, Engine Machine wrote:
On Tuesday, 16 August 2016 at 17:39:14 UTC, Lodovico Giaretta 
wrote:
On Monday, 15 August 2016 at 19:31:14 UTC, Engine Machine 
wrote:

[...]


I don't know if this is exactly what you want:

=
import std.traits: hasMember;

struct Q(T)
if (hasMember!(T, "x"))
{
T s;

@property auto x() { return s.x; }
}
auto makeQ(T)(auto ref T val)
{
return Q!T(val);
}

auto s = myTypeWithFieldX();
auto q = makeQ(s);
assert(q.x == s.x);
=

`Q` can store any type with an `x` field and gives access to 
it. The auxiliary function `makeQ` acts as a constructor for 
`Q` with template parameter deduction.


I realize now that D simply cannot do what I ask directly 
because It's type parameters are part of the type. It can't be 
told that in some cases they are not. Any use of the 
parameters, as I am using them, will result in this issue.


I'm now trying a different method which builds the based types 
using partial oop and partial CT code. The CT code is only for 
performance and convenience anyways.


You are right in that it is not possible to strip part of the 
type informations.


The only problem is Q is still defined by T. Your makeQ then 
requires the type implicitly, which I don't necessarily have. 
You've simply added complexity to the problem but the issue is 
still there.


How is it possible that you don't have T? Your variable will 
surely have a type! Can you provide more background? Because 
maybe I'm not completely getting your point here...