-
-
Notifications
You must be signed in to change notification settings - Fork 739
Add lvalue/rvalue traits #1261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add lvalue/rvalue traits #1261
Conversation
|
||
|
||
/** | ||
Creates and lvalue or rvalue of type $(D T) for $(D typeof(...)) and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "creates and".
The latter. Fixed noted issues. |
I think void main() {
int x = 1;
enum b = isLvalue!(1 + x); // add expression makes rvalue but...
// Error: variable x cannot be read at compile time --> doesn't work!
} We cannot fix the problem so it is an intrinsic limitation which comes from that |
I can agree with adding |
@9rnsr, I just changed |
Rebased to fix merge conflicts. Also I prefer my |
To @9rnsr:
So, we can't use Or we can make static assert( __traits(compiles, expectLvalue(i)));
static assert(!__traits(compiles, expectLvalue(i + 1)));
static assert(!__traits(compiles, expectLvalue(f))); |
The limitation is comes from that a template cannot take a runtime expression. template X(T...) {}
void main() {
int n;
alias X1 = X!(n); // take a symbol `n`.
alias X2 = X!(int); // take a type `int`.
alias X3 = X!(1); // take a value `1`.
//alias X4 = X!(n + 1); // cannot take an expression `n + 1`
} This is current language design of D, not a bug. So we cannot implement
It is useless, because |
Other ugly but safe implementable interfaces: Using mixin isLvalue!(`l_i`, q{i});
static assert(l_i);
mixin isLvalue!(`l_i1`, q{i + 1});
static assert(!l_i1);
static assert(!__traits(compiles, { mixin isLvalue!(`l_x`, q{x}); })); Using string static assert( mixin(isLvalue!q{i}));
static assert(!mixin(isLvalue!q{i + 1}));
static assert(!__traits(compiles, mixin(isLvalue!q{x}))); |
Don't understand. I shown usage in examples. |
You mean "with this interface". What about other interfaces? Too ugly? |
Yes, as you explained, we can provide it with the premise of using mixin. But it is too ugly. I cannot agree with it. |
Me too. What about the first of proposed "other interfaces", |
What's the status here? I understand that there are problems with A lot of code uses T.init instead, which is only about 90% accurate in what it is actually testing... |
What about to make |
Package maybe, but not undocumented, that never ends well. Are there many use cases for |
@9rnsr, I undocumented |
Can't you make it package?
Yes: Given the discussions of
Not supporting this syntax would just add one more pitfal in the pitfals that are initialization. Ditto for |
I still think this |
Of course is is. So it is undocumented now and used only in unittests, where it is needed. Or must I mark it |
You can test unittest
{
void accepstsLvalue(T)(ref T lval);
...
static assert(!__traits(compiles, acceptsLvalue(rvalueOf!T)));
static assert( __traits(compiles, acceptsLvalue(lvalueOf!T)));
} I recommend to remove isLvalue definition completely. |
To @monarchdodra: |
OK. Will do now. |
@9rnsr, what about my |
As my previous |
@denis-sh Hmm, how about this to disallow setter syntax? template rvalueOf(T)
{
@property T rvalueOf(inout int = 1);
@property T rvalueOf(inout int) @disable; // Disallow rvalueof!T = 1; syntax
}
/// ditto
template lvalueOf(T)
{
@property ref T lvalueOf(inout int = 1);
@property ref T lvalueOf(inout int) @disable; // Disallow lvalueof!T = 1; syntax
} The error message for the setter syntax misuse is not so friendly, but it works. |
As @monarchdodra noted, |
Added |
@@ -4085,6 +4090,55 @@ unittest | |||
} | |||
|
|||
|
|||
struct __InoutWorkaroundStruct{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private
.
Also, could you document what you are working around? I have no idea what the whole inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init
is about.
To @monarchdodra:
I was unsure
OK. |
I hadn't thought of that actually. I don't know then. It seems to work as private. |
enum hasElaborateAssign = is(typeof(S.init.opAssign(S.init))) || | ||
is(typeof(S.init.opAssign(lvalueOf))) || | ||
enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) || | ||
is(typeof(S.init.opAssign(lvalueOf!S))) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well also make these:
+ enum hasElaborateAssign = is(typeof(lvalueOf!S.opAssign(rvalueOf!S))) ||
+ is(typeof(lvalueOf!S.opAssign(lvalueOf!S))) ||
No?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well also make these
...
No?
Yes we can but I'd like to let it be this way as T.init.func
looks already common. If it is bad, lets discuss and replace it everywhere.
This pull looks merge-ready to me. Any body have anything else to add? @9rnsr ? |
@9rnsr, ping. Are you OK with this? |
The LGTM. |
CRLF EOLs were introduced in ea72723 commit of pull dlang#1261.
rvalueOf
/lvalueOf
(commits extracted from pull #954)