www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Wrapper around a recursive data type

reply drug007 <drug2004 bk.ru> writes:
I need to generate some meta info of my data types. I do it this 
[way](https://gist.github.com/drug007/b0a00dada6c6ecbf46b4f6988401d4e2):
```D
import std.range, std.format, std.stdio, std.traits;

struct NestedType
{
     string s;
     double d;
}

struct Node
{
     string value;
     int i;
     NestedType nt;
     // Node[] children; // It makes Node to be a recursive data types
}

template Meta(A)
{
     static if (isRandomAccessRange!A)
         alias Meta = RaRMeta!A;
     else static if (isSomeString!A || isIntegral!A || isFloatingPoint!A)
         alias Meta = ScalarMeta!A;
     else
         alias Meta = AggregateMeta!A;
}

struct RaRMeta(A)
{
     alias ElementType = typeof(A.init[0]);
     Meta!ElementType[] model;
}

struct ScalarMeta(A) {}

struct AggregateMeta(A)
{
     static foreach (member; __traits(allMembers, A))
         mixin("Meta!(typeof(A.%1$s)) %1$s;".format(member));
}

void main()
{
     auto meta = Meta!Node();

     assert(meta.value == ScalarMeta!string());
     assert(meta.i == ScalarMeta!int());
     assert(meta.nt == AggregateMeta!NestedType());

     assert(meta.nt.s == ScalarMeta!string());
     assert(meta.nt.d == ScalarMeta!double());
}
```
It works. But when I try to wrap around a recursive data type (uncomment 
`children` member of `Node` type) it fails because during instantiating 
of `Meta!Node` it needs complete `Meta!Node` type to process `children` 
member of `Node`.

How can I "break" this recursion or some other work around to fix it?
Jul 08
next sibling parent reply user1234 <user1234 12.de> writes:
On Monday, 8 July 2024 at 08:56:51 UTC, drug007 wrote:
 I need to generate some meta info of my data types. I do it 
 this [...]
 How can I "break" this recursion or some other work around to 
 fix it?
Use `Node*[]` for the children type. That way the compiler knows the size of the (previously) problematic member. In other words, instead of the need to know `Node` size, the compiler will not look further, it's a pointer.
Jul 08
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On Monday, 8 July 2024 at 13:29:05 UTC, user1234 wrote:
 On Monday, 8 July 2024 at 08:56:51 UTC, drug007 wrote:
 I need to generate some meta info of my data types. I do it 
 this [...]
 How can I "break" this recursion or some other work around to 
 fix it?
Use `Node*[]` for the children type. That way the compiler knows the size of the (previously) problematic member. In other words, instead of the need to know `Node` size, the compiler will not look further, it's a pointer.
This isn't the issue exactly. `Node[]` is a pointer as well. The issue is that the template recursively depends on itself. You would run into the same issue if the template recursed on the type of the pointed-at value. -Steve
Jul 08
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Monday, 8 July 2024 at 08:56:51 UTC, drug007 wrote:
 I need to generate some meta info of my data types. I do it 
 this 
 [way](https://gist.github.com/drug007/b0a00dada6c6ecbf46b4f6988401d4e2):
 ```D
 import std.range, std.format, std.stdio, std.traits;

 struct NestedType
 {
     string s;
     double d;
 }

 struct Node
 {
     string value;
     int i;
     NestedType nt;
     Node[] children; // It makes Node to be a recursive data 
 types
 }
 ```
Can you post the error and the exact code that fails? I tried building this (with the children uncommented out) and it works fine. -Steve
Jul 08
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On Tuesday, 9 July 2024 at 03:04:50 UTC, Steven Schveighoffer 
wrote:

 Can you post the error and the exact code that fails? I tried 
 building this (with the children uncommented out) and it works 
 fine.
Ignore this, I didn't really read the whole message. -Steve
Jul 08
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Monday, 8 July 2024 at 08:56:51 UTC, drug007 wrote:
 How can I "break" this recursion or some other work around to 
 fix it?
A few ideas: 1. If it's immediately recursive (that is, contains a pointer to itself), just use the type itself somehow. You may not be able to do this with recursive templates. 2. If the data itself is static, and not actually containing different things, defer the construction of the Meta members until needed. In other words, make them structs with a member which accesses the meta when requested. 3. In a project I have which constructs a parallel type on existing types, I use `opDispatch` to defer instantiation of the members until later. This may or may not work for you depending on the use case (you can't introspect `opDispatch`). -Steve
Jul 08
parent drug007 <drug2004 bk.ru> writes:
On 09.07.2024 06:54, Steven Schveighoffer wrote:
 On Monday, 8 July 2024 at 08:56:51 UTC, drug007 wrote:
 How can I "break" this recursion or some other work around to fix it?
A few ideas: 1. If it's immediately recursive (that is, contains a pointer to itself), just use the type itself somehow. You may not be able to do this with recursive templates. 2. If the data itself is static, and not actually containing different things, defer the construction of the Meta members until needed. In other words, make them structs with a member which accesses the meta when requested. 3. In a project I have which constructs a parallel type on existing types, I use `opDispatch` to defer instantiation of the members until later. This may or may not work for you depending on the use case (you can't introspect `opDispatch`). -Steve
Decided to use untyped array (like void[]) and then a decorator to make it typed one. It seems to be working, testing in progress.
Jul 14