D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 9705 - property parameter-less template function not resolved in typeof
Summary: property parameter-less template function not resolved in typeof
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-03-12 11:44 UTC by monarchdodra
Modified: 2020-03-21 03:56 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description monarchdodra 2013-03-12 11:44:14 UTC
There is a construct, where one defines a parameter template function, so that the compiler can infer its attributes.

The problem is that when said function is a property, it doesn't mix with traits, because it fails the typeof blocks. Explanation:

//----
import std.range;

struct Infered
{
    size_t length()(){return 0;}
}

void main()
{
    Infered r;
    auto len = r.length; //OK

    static assert(hasLength!Infered);
        //Error: static assert  (hasLength!(Infered)) is false

    static assert(is(typeof(r.length) : ulong));
        //Error: static assert  (is(typeof(r.length()()) : ulong)) is false

    pragma(msg, typeof(r.length).stringof);
        //Error: expression (r.length()()) has no type
        //   while evaluating pragma(msg, (_error_).stringof)
}
//----

Such usage is very interesting for wrapper ranges, but they are the most vulnerable: Are concerned:
hasLength.
isForwardRange.
isRandomAccessRange.

One workaround is to make the call outside of the typeof, and store the result, and then test result itself eg is(typeof(len) : ulong)). Doing this would shuffle around a lot of code though, so I don't think it's worth doing it.
Comment 1 basile-z 2017-12-21 01:32:02 UTC
The specs say that typeof(F) gets the function F return type only when it's marked @property.

(https://dlang.org/spec/declaration.html#typeof, ยง4)

When this rule is followed, the assertions are valid:

```
import std.range;

struct Infered
{
    size_t length()() @property {return 0;}
}

void main()
{
    Infered r;
    auto len = r.length; //OK
    static assert(hasLength!Infered); //OK
    static assert(is(typeof(r.length) : ulong)); //OK
    pragma(msg, typeof(r.length).stringof); //OK
}
```