Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 25, 2014 Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
I have problem with understanding of work of modifiers const, inout, immutable modifiers. As I understand inout keyword is intended to consume const, immutable and data without modifiers. It's how I expect it to work otherwise I don't understand what is the purpose of inout. In current implementation of language it looks like (it's just my feeling) that it's completly other modifier that connects badly with const and immutable. In this case I don't understand sense of it. Also I have strange feelings about shared, because it's not widely used in code that I'm experienced to see and lacks of good usage examples. May main question is that I don't understand sense of this error: Error: cannot implicitly convert expression (&c) of type const(Cookie)* to inout(Cookie)* It occured in the following code. Can someone understand what I'm doing wrong? Or is it a bug or something? struct Cookie { string name; string value; string domain; string path; string expires; bool isHTTPOnly; bool isSecure; void opAssign(string rhs) { value = rhs; } string toString() { string result = `Set-Cookie: ` ~ name ~ `=` ~ value; if( domain.length > 0 ) result ~= `; Domain=` ~ domain; if( path.length > 0 ) result ~= `; Path=` ~ path; if( expires.length > 0 ) result ~= `; Expires=` ~ expires; if( isHTTPOnly ) result ~= `; HttpOnly`; if( isSecure ) result ~= `; Secure`; return result; } } class ResponseCookies { Cookie[] _cookies; //..... inout(Cookie)* opBinaryRight(string op)(string name) inout if(op == "in") { foreach( ref inout(Cookie) c; _cookies ) if( c.name == name ) return &c; //Error is here return null; } } |
March 25, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | On 03/25/2014 12:20 PM, Uranuz wrote: > I have problem with understanding of work of modifiers const, inout, > immutable modifiers. I am sure you know these as well, but here is my quick list: const: "I shall not modify data" immutable: "I demand immutable data" inout: "Whatever the actual type qualifier is" > As I understand inout keyword is intended to consume const, > immutable and data without modifiers. Yes. Further, the code is compiled as 'const' (because const is compatible with mutable, immutable, and const). > I don't understand what is the purpose of inout. So that the following function works with any kind of int array: inout(int)[] first_two(inout(int)[] arr) { // (input validation omitted) return arr[0..2]; } We don't have to write three overloads just for these qualifiers. (Yes, templates with constraints can be used as well.) > Error: cannot implicitly convert expression (&c) of type const(Cookie)* > to inout(Cookie)* Your code compiles with the development branch of dmd. What version are you using? Ali |
March 25, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | > Your code compiles with the development branch of dmd. What version are you using?
>
Now I'm using 2.064. May be this bug is already fixed. In 2.065 I experience problem that std.json library module is not compatible with code written for previous versions. This is why I returned to 2.064. As far as I understand these breaking changes were a mistake. Now I don't know how to deal with it. I'm not sure that using old Phobos verion with new compiler could be good solution. If were a mistake It doesn't sound reasonable to change existing code to compile with this version.
|
March 25, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | On 03/25/2014 02:01 PM, Uranuz wrote: >> Your code compiles with the development branch of dmd. What version >> are you using? >> > Now I'm using 2.064. Still compiles for me. Could you please show us a minimal main() as well. Thank you, Ali |
March 26, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | >
> Still compiles for me. Could you please show us a minimal main() as well.
>
> Thank you,
> Ali
Yes. This exact piece of code compiles in 2.064, but it doesn't
compile in my project. I don't know how to localize the problem
yet. It's very strange. I have tried to create class instance
with different modifiers (const, inout, immutable), because it
could be because of type of array that I try to access. Very
strange. I'll try to repeat it.
|
March 26, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | Source of error is that I have also the following methods inside ResponseCookise class: void opIndexAssign(string value, string name) { auto cookie = name in this; if( cookie is null ) _cookies ~= Cookie(name, value); else cookie.value = value; } void opIndexAssign( ref Cookie value, string name ) { auto cookie = name in this; if( cookie is null ) _cookies ~= value; else *cookie = value; } In 2.065 I get other error message than in 2.064, but it still not very informative. Why I get message inside *in* operator but not in *opIndexAssign*?. And how could I solve this? /d800/f144.d(49): Error: cannot implicitly convert expression (&c) of type inout(const(Cookie))* to inout(Cookie)* /d800/f144.d(38): Error: template instance f144.ResponseCookies.opBinaryRight!"in" error instantiating /d800/f144.d(38): Error: rvalue of in expression must be an associative array, not f144.ResponseCookies |
March 26, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | If inout is treated as const does it mean that in this operator I can't assign new value to cookie object. In this case it means that I still should make separate class method with the same body to woraround this. I think that it's a bug. Am I right?
> void opIndexAssign(string value, string name)
> { auto cookie = name in this;
> if( cookie is null )
> _cookies ~= Cookie(name, value);
> else
> cookie.value = value;
> }
|
March 26, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | On Tuesday, 25 March 2014 at 19:20:10 UTC, Uranuz wrote:
> In this case I don't understand sense of it. Also I have strange feelings about shared, because it's not widely used in code that I'm experienced to see and lacks of good usage examples.
shared is used for low-level multithreading, if you're not experienced in it, use safer methods from std.concurrency.
|
March 26, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uranuz | On 03/26/2014 01:21 AM, Uranuz wrote: > If inout is treated as const does it mean that in this operator I can't > assign new value to cookie object. I have not investigated the compiler code but the following is very logical to me. inout is not a template mechanism. The code gets compiled once. What happens is, the inout from some variable is transferred to some other variable(s). Since inout must work with mutable, const, and immutable, and since const binds to all three, it is easy for the compiler to assume inout is const inside the code and reject code that tries to modify an inout variable (even if inout is 'mutable' for some calls to the function). After compiling the code, the compiler also ensures that the inout that is returned from the function is compatible with the calling code. For example, if the source inout array were immutable, a slice of it should not be assigned to a mutable slice at the caller site: inout(int)[] foo(inout(int)[] arr) { return arr; } immutable(int)[] imm = // ...; int[] result = foo(imm); // ERROR > In this case it means that I still > should make separate class method with the same body to woraround this. > I think that it's a bug. Am I right? It is not a bug. If the member function makes modifications to the object, it cannot be inout, because it can work only with mutable objects. Ali |
March 26, 2014 Re: Problem with taking inout, const references | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | I modified this with casting pointer to pointer to *inout* and it compiles then. inout(Cookie)* opBinaryRight(string op)(string name) inout if(op == "in") { foreach( ref inout(Cookie) c; _cookies ) if( c.name == name ) return cast(inout(Cookie)*) &c; //Error is here return null; } As I think compiler may be should create const version and mutable version of this function. In case when it's mutable it should return pointer to mutable pointer to *const* data when function is const. In first case it will be able to modify variable from outside using this pointer to mutable. Otherwise if pointer to *const* produced modification is not allowed. I don't understand why compiler produce pointer to const, when inout "converts" to mutable. I think that compiler should check that object field is not modified inside it's const method, but I don't understand why it produces pointer to nonconst in case when object field shouldn't be const. In case when all is treated like const I don't understand how *inout* could be useful to get mutable references and pointers as result of *inout* method when object (and it's fields) are mutable. Is this behaviour forbidden for some reason that I don't know? |
Copyright © 1999-2021 by the D Language Foundation