Bug 15634 – new __traits request: isLvalue

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-02-01T16:57:52Z
Last change time
2020-06-15T12:11:37Z
Assigned to
No Owner
Creator
Steven Schveighoffer

Comments

Comment #0 by schveiguy — 2016-02-01T16:57:52Z
If I want a template constraint that requires that some alias/member is an lvalue, I have to do something very complex (courtesy of Meta from the forums): template yieldsLval(Aggregate, alias member) { import std.traits: ReturnType; import std.functional: FunctionTypeOf; import std.typetuple: staticIndexOf; static if (isSomeFunction!member) { enum yieldsLval = __traits(compiles, { alias Ftype = FunctionTypeOf!member; void takesLval(ref ReturnType!Ftype) {} takesLval(Ftype()); }); } //It's a member variable else static if (staticIndexOf!(member.stringof, FieldNameTuple!Aggregate) > -1) enum yieldsLval = true; else static assert(false, "Symbol " ~ member.stringof ~ " is not a member function or variable of " ~ Aggregate.stringof); } struct S { int x; ref int y() { return x; } int z() { return 1; } enum f = 0; } void main() { static assert(yieldsLval!(S, S.y)); static assert(yieldsLval!(S, S.x)); static assert(!yieldsLval!(S, S.z)); static assert(!__traits(compiles, yieldsLval!(S, S.f))); } I'm assuming the compiler has this information pretty handy, since it complains about using rvalues where lvalues are required all the time. Can we get a __traits call to get this info out of the compiler? For reference: https://forum.dlang.org/post/[email protected]
Comment #1 by stanislav.blinov — 2020-06-13T12:07:56Z
Stumbled on this via a forum thread (four years later, yay), and honestly I find this request rather strange. There is a trait that provides such information for functions - the getFunctionAttributes. It already existed at the time of this issue report, and is even touched upon in aforementioned forum thread, albeit in Phobos disguise. However, the "some alias/member" may be (among others): - an overloaded function - a function template with auto ref parameters In both of those cases, a __trait won't be able to provide the information required, since symbol alone is simply insufficient. Overloads would need to be tested one by one, carefully matching arguments; templates would have to be instantiated, again carefully matching arguments. Consider: struct S { string x; // NOTE: y is overloaded void y() {} ref y(return ref int z) { return z; } float y(float z) { return z; } // whether it returns rvalue or lvalue depends on what is passed auto ref tpl(Args...)(auto ref Args args) { static if (args.length) return args[0]; } } static assert(__traits(hypotheticalIsLvalue, S.y)); // which `y` ??? static assert(__traits(hypotheticalIsLvalue, S.tpl)); // ???
Comment #2 by schveiguy — 2020-06-15T12:11:37Z
Yeah, I think this was a suggestion from someone because the code he used to do the same thing was really complex. But later, someone posted a much simpler solution (just try passing the result into a ref lambda). I don't really need this. I should have closed it immediately. Thanks.