Thread overview
Checking a (base) type and accepting any specialization?
Jun 08
monkyyy
Jun 08
monkyyy
Jun 08
monkyyy
June 08

I have following situation:

I have a struct Routine (base type) and its specializations !n.

struct Routine (uint argscount = 1) {
    string name;
    void delegate(inout Arguments!argscount) return call;
}

const auto ROUTINES = [
    Routine!3(":input", toDelegate(&routine_input)),
    Routine!2(":print", toDelegate(&routine_print)),
];

I understand why the given types are not compatible.
But not how I can store any base type regardless its specialization.

June 08

On Sunday, 8 June 2025 at 14:29:27 UTC, mitgedanken wrote:

>

I have following situation:

I have a struct Routine (base type) and its specializations !n.

struct Routine (uint argscount = 1) {
    string name;
    void delegate(inout Arguments!argscount) return call;
}

const auto ROUTINES = [
    Routine!3(":input", toDelegate(&routine_input)),
    Routine!2(":print", toDelegate(&routine_print)),
];

I understand why the given types are not compatible.
But not how I can store any base type regardless its specialization.

the most correct answer is nested templates

template foo(T){
struct foo(T data){
  ...
}}

You can probably find an api workaround in ctfe with assert(__ctfe) to make it work better; but when all else fails this ends up being nessery(most cant read even simple ones tho)

madness and compile bugs:
struct foo(T, T data) will work once, your names a little new for me to attempt to explain why

you should probably just use an alias:

struct Routine(alias argscount = 1) {
	alias T=typeof(argscount);
	T[argscount] data;
}
unittest{
	Routine!(ubyte(2)) foo;
	Routine!3 bar;
}
June 08
On Sunday, 8 June 2025 at 16:33:08 UTC, monkyyy wrote:
>
> the most correct answer is nested templates
> ```d
> template foo(T){
> struct foo(T data){
>   ...
> }}
> ```
> You can probably find an api workaround in ctfe with `assert(__ctfe)` to make it work better; but when all else fails this ends up being nessery(most cant read even simple ones tho)
> ---
> madness and compile bugs:
> `struct foo(T, T data)` will work *once*, your names a little new for me to attempt to explain why
> ---
> you should probably just use an alias:
> ```d
> struct Routine(alias argscount = 1) {
> 	alias T=typeof(argscount);
> 	T[argscount] data;
> }
> unittest{
> 	Routine!(ubyte(2)) foo;
> 	Routine!3 bar;
> }
> ```

June 08

On Sunday, 8 June 2025 at 14:29:27 UTC, mitgedanken wrote:

>

I have following situation:

I have a struct Routine (base type) and its specializations !n.

struct Routine (uint argscount = 1) {
    string name;
    void delegate(inout Arguments!argscount) return call;
}

const auto ROUTINES = [
    Routine!3(":input", toDelegate(&routine_input)),
    Routine!2(":print", toDelegate(&routine_print)),
];

I understand why the given types are not compatible.
But not how I can store any base type regardless its specialization.

I thought the code was self-explanatory. But I was wrong about that. Whereby you are going in the right direction.

I have a struct "Argument".

struct Argument (alias data) {
    alias TData = typeof(Data);
    TData data;
}
struct Arguments (uint argcount, alias Data) {
    Argument!Data[argcount] args;
}
// Is this struct needed? An alternative please.

And a struct "Routine".

struct Routine(uint argcount, alias Data, alias ReturnValue) {
    alias TRet = typeof(ReturnValue);
    alias TArg = Argument!(Data);
    alias Args = Argument!Data[argcount];

    static if (argCount > 0) {
        TRet delegate(TArg Args) call;
    }
    else {
        TRet delegate() call;
    }
}

I want to specify through these structs that a routine ...
A. returns the type TRet
B. how many arguments (and their type*) it needs

Background
I write a simple programming language. For this I define routines that can be called by the user. The routines are therefore predefined. But they should be read by a const. Of course I could also build it into the parser/lexer, like everything else, but that is not my problem.

Does this help?

June 08

On Sunday, 8 June 2025 at 18:44:15 UTC, mitgedanken wrote:

>

// Is this struct needed? An alternative please.

>

I want to specify through these structs that a routine ...
A. returns the type TRet
B. how many arguments (and their type*) it needs

template foo(T...){
	enum len=T.length;
	static if(T.length>0&& ! is(T[0]==void)){
		alias first=T[0];
	} else {
		alias first=void;
	}
}

unittest{
	alias bar=foo!(int,13.37,true);
	static assert(bar.len==3);
	static assert(foo!().len==0);
	static assert(is(bar.first==int));
}

crash course of templates ugly syntax:

  1. templates can store groups of thingz
  2. alias hold types, enums hold litterals(the exceptions to this rule are complicated)
  3. throw static in front of keywords and hope it works
  4. T... is magic, learn all the syntax of AliasSeq
  5. pragma(msg, and __traits are ugly but nessery

read the template book when you start running into major problems

June 08

On Sunday, 8 June 2025 at 14:29:27 UTC, mitgedanken wrote:

>

I understand why the given types are not compatible.
But not how I can store any base type regardless its specialization.

I know OO is mostly looked down upon, but if you have a common root class and each subclass specializes, you can have a variable of the root class' type and it'll store pointers to either.

Andy