2
votes

I'm trying to write a template that will return an AliasSeq of return types from an AliasSeq of functions. However in my code when I try to compile it, it tells me Error: type (...) has no value

This is my code I have so far:

template ReturnTypesFromFunctions(Functions...)
{
    auto ReturnTypesFromFunctions()
    {
        alias functions = AliasSeq!();
        foreach(fn; Functions)
        {
            functions = AliasSeq!(functions, ReturnType!fn);
        }
        return functions;
    }
}

Basically what I'm trying to do is automatically generating an AliasSeq array from this:

int a();
bool b();
double c();

alias functions = AliasSeq!(a, b, c);
alias returnTypes = ReturnTypesFromFunctions!functions;
// returnTypes -> AliasSeq [int, bool, double]

But with the current code it will result in these errors:

Error: type (int) has no value
Error: type (bool) has no value
Error: type (double) has no value
Error: type () has no value

It has probably to do with the auto because the compiler can't find a type from the functions alias. However there is no type that would represent the AliasSeq because the function itself is for finding out the type so I can use it elsewhere.

2

2 Answers

4
votes

Once you have defined an alias, you cannot modify it. You also cannot return AliasSeqs from functions, as they are not first-class values.

The correct way to do this would be via a recursive template...

template ReturnTypesFromFunctions(Funcs...) {
    static if(Funcs.length == 0)
        alias ReturnTypesFromFunctions = AliasSeq!();
    else
        alias ReturnTypesFromFunctions = AliasSeq!(ReturnType!(Funcs[0]), ReturnTypesFromFunctions!(Funcs[1..$]));
}

... However, in this case, you're just reinventing the staticMap template, so just use that instead.

alias returnTypes = staticMap!(ReturnType, functions);
3
votes

This sounds like a good use for staticMap

import std.meta, std.traits;

template ReturnTypesFromFunctions(Functions...) {
  alias ReturnTypesFromFunctions = staticMap!(ReturnType, Functions);
}

int a();
bool b();
double c();

alias functions = AliasSeq!(a,b,c);
alias returnTypes = ReturnTypesFromFunctions!functions;

pragma(msg, returnTypes); // (int, bool, double)