Thread overview
Retrieve the return type of the current function
May 05, 2020
learner
May 05, 2020
Adam D. Ruppe
May 05, 2020
learner
May 05, 2020
Jonathan M Davis
May 05, 2020
Meta
May 05, 2020
Meta
May 06, 2020
Jacob Carlborg
May 06, 2020
learner
May 05, 2020
Good morning,

Is it possible something like this?

```
int foo() {

    __traits(some_trait, some_generic_this) theInt = 0;
```

I mean, without using the function name in the body, like ReturnType!foo ?

May 05, 2020
On Tuesday, 5 May 2020 at 16:36:48 UTC, learner wrote:
> I mean, without using the function name in the body, like ReturnType!foo ?

even easier:

typeof(return)
May 05, 2020
On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote:

> typeof(return)

Thank you, that was indeed easy!

Is it possible to retrieve also the caller return type? Something like:

```
int foo() {
    return magic();
}

auto magic(maybesomedefaulttemplateargs = ??)() {
    alias R = __traits(???); // --> int!
}
```

Mixin templates maybe?
May 05, 2020
On Tuesday, May 5, 2020 11:11:53 AM MDT learner via Digitalmars-d-learn wrote:
> On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote:
> > typeof(return)
>
> Thank you, that was indeed easy!
>
> Is it possible to retrieve also the caller return type? Something like:
>
> ```
> int foo() {
>      return magic();
> }
>
> auto magic(maybesomedefaulttemplateargs = ??)() {
>      alias R = __traits(???); // --> int!
> }
> ```
>
> Mixin templates maybe?

A function is compiled completely independently of where it's used, and it's the same regardless of where it's used. So, it won't ever have access to any information about where it's called unless it's explicitly given that information.

A function template will be compiled differently depending on its template arguments, but that still doesn't depend on the caller at all beyond what it explicitly passes to the function, and if the same instantiation is used in multiple places, then that caller will use exactly the same function regardless of whether the callers are doing anything even vaguely similar with it.

So, if you want a function to have any kind of information about its caller, then you're going to have to either explicitly give it that information via a template argument or outright generate a different function with a string mixin every time you use it. So, you could do something like

auto foo(T)(int i)
{
    ...
}

string bar(string s, int i)
{
    return!string(i);
}

or

string bar(string s, int i)
{
    return!(typeof(return))(i);
}

but you're not going to be have foo figure out anything about its caller on its own.

- Jonathan M Davis



May 05, 2020
On Tuesday, 5 May 2020 at 17:11:53 UTC, learner wrote:
> On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote:
>
>> typeof(return)
>
> Thank you, that was indeed easy!
>
> Is it possible to retrieve also the caller return type? Something like:
>
> ```
> int foo() {
>     return magic();
> }
>
> auto magic(maybesomedefaulttemplateargs = ??)() {
>     alias R = __traits(???); // --> int!
> }
> ```
>
> Mixin templates maybe?

You *can* use mixin templates to access the caller's scope, which means typeof(return) will refer to the caller's return type, instead of the callee's. However, there's no way to both mixin and call the mixin template in a single line, so it's not DRY:

int foo()
{
    mixin magic;
    return magic();
}

mixin template magic()
{
    alias CallerRet = typeof(return);
    CallerRet magic()
    {
        return CallerRet.init;
    }
}

void main()
{
    foo();
}

Maybe somebody else knows a way to get around having to first mixin magic.
May 05, 2020
On Tuesday, 5 May 2020 at 18:19:00 UTC, Meta wrote:
> mixin template magic()
> {
>     alias CallerRet = typeof(return);
>     CallerRet magic()
>     {
>         return CallerRet.init;
>     }
> }

Small edit: you can remove the "CallerRet" alias by doing the following:

mixin template magic()
{
    typeof(return) magic()
    {
        return typeof(return).init;
    }
}


Though I wouldn't really recommend it as it's very confusing, IMO. This works because "typeof(return)" in the return position here refers to the caller's scope, while "typeof(return)" inside the function refer's to the function's scope.

May 06, 2020
On 2020-05-05 19:11, learner wrote:
> On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote:
> 
>> typeof(return)
> 
> Thank you, that was indeed easy!
> 
> Is it possible to retrieve also the caller return type? Something like:

Yes, kind of:

void foo(string caller = __FUNCTION__)()
{
    import std.traits : ReturnType;

    alias R = ReturnType!(mixin(caller));
    static assert(is(R == int));
}

int bar()
{
    foo();
    return 0;
}


-- 
/Jacob Carlborg
May 06, 2020
On Wednesday, 6 May 2020 at 08:04:16 UTC, Jacob Carlborg wrote:
> On 2020-05-05 19:11, learner wrote:
>> On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote:
>> 
>>> typeof(return)
>> 
>> Thank you, that was indeed easy!
>> 
>> Is it possible to retrieve also the caller return type? Something like:
>
> Yes, kind of:
>
> void foo(string caller = __FUNCTION__)()
> {
>     import std.traits : ReturnType;
>
>     alias R = ReturnType!(mixin(caller));
>     static assert(is(R == int));
> }
>
> int bar()
> {
>     foo();
>     return 0;
> }

Awesome and beautiful, thank you!