Bug 9705 – property parameter-less template function not resolved in typeof
Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-03-12T11:44:14Z
Last change time
2020-03-21T03:56:39Z
Assigned to
No Owner
Creator
monarchdodra
Comments
Comment #0 by monarchdodra — 2013-03-12T11:44:14Z
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 by b2.temp — 2017-12-21T01:32:02Z
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
}
```