www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Auto keyword with const variable

reply "Alex H" <myemail email.com> writes:
This code:

void test(const int n)
{
	auto j = n;
	j++;
}

Gives this error:
cannot modify const expression j


Is this considered a feature or a bug? I would assume most people
wouldn't want new variables inheriting const.
Jul 24 2013
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Alex H:

 void test(const int n)
 {
 	auto j = n;
 	j++;
 }

 Gives this error:
 cannot modify const expression j


 Is this considered a feature or a bug? I would assume most 
 people wouldn't want new variables inheriting const.
It's a bit annoying. I don't remember people discussing this small problem. I don't know if it's easy to "fix" it and what side effects such change could cause. Bye, bearophile
Jul 24 2013
parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 24.07.2013 11:39, schrieb bearophile:
 Alex H:

 void test(const int n)
 {
 	auto j = n;
 	j++;
 }

 Gives this error:
 cannot modify const expression j


 Is this considered a feature or a bug? I would assume most
 people wouldn't want new variables inheriting const.
It's a bit annoying. I don't remember people discussing this small problem. I don't know if it's easy to "fix" it and what side effects such change could cause.
should that be fixed - i don't think that any auto removal of const, immutable, shared or anything else should just happen silently and how would it look to preserve the const if auto would auto-rip it of?
Jul 24 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
dennis luehring:

 and how would it look to preserve the const if auto would 
 auto-rip it of?
You could write: immutable j = n; For every default behavour you need a way to implement the other nicely :-) Currently for the problem of the OP you can use this: Unqual!(typeof(n)) j = n; Bye, bearophile
Jul 24 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 24 July 2013 at 10:01:14 UTC, bearophile wrote:
 dennis luehring:

 and how would it look to preserve the const if auto would 
 auto-rip it of?
You could write: immutable j = n; For every default behavour you need a way to implement the other nicely :-) Currently for the problem of the OP you can use this: Unqual!(typeof(n)) j = n; Bye, bearophile
Definitly. Auto means "same type". I think it could be OK if it followed IFTI rules? After all, in concept, it's kind of the same mechanism. I wouldn't go any further than that though. //---- void foo(T)(T t) { pragma(msg, T.stringof); } void main(string[] args) { immutable int[] i = [1, 2, 3]; foo(i); auto j = i; pragma(msg, typeof(j).stringof); } //---- immutable(int)[] immutable(int[]) //---- Problem: I don't really see a good usecase for making auto have special IFTI behavior. Keeping it to "same type, 100% of the time" seems like the best.
Jul 24 2013
parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 07/24/13 12:09, monarch_dodra wrote:
 Keeping it to "same type, 100% of the time" seems like the best.
No, it's a design bug. The head qualifier(s) should always be stripped when copying objects. Stripping is always fine (ie safe), not doing it just creates other problems, like the one in OP, or unnecessary template bloat. The IFTI special cases that are already there are just handling one of the symptoms. As you can always declare something as 'immutable' or 'const', instead of 'auto', the default would have to be head-mutable [1]. Ie, this would then work: const int a; immutable b = a; // immutable int const c = a; // const int auto d = a; // int Right now, you have to do `auto d = cast()a;` or use the Unqual hack... artur [1] If D had a `var` qualifier, then defaulting to 'const' might be better. But it doesn't.
Jul 24 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 24 July 2013 at 10:37:40 UTC, Artur Skawina wrote:
 On 07/24/13 12:09, monarch_dodra wrote:
 Keeping it to "same type, 100% of the time" seems like the 
 best.
No, it's a design bug. The head qualifier(s) should always be stripped when copying objects. Stripping is always fine (ie safe)
Nope. Stop. Wrong. Qualification is transitive in D, unlike in C++. Even when copying, stripping qualification is not safe: //---- struct S { int* p; } void main() { immutable i = 1; auto a = immutable(S)(&i); auto b = cast(S)a; //Unsafe cast *b.p = 2; //This'll probably crash on a linux //Program corrupted by here. assert(i == *&i); //This fails (!!!) on my win32 } //---- Long story short, never cast to Unqual. Always to an implicit cast, and let the compiler complain if it is illegal: //---- struct S1 { int a; } struct S2 { int* p; } void main() { immutable i = 1; auto a1 = immutable(S1)(i); auto a2 = immutable(S2)(&i); S1 b1 = a1; //OK! S2 b2 = a2; //Error: cannot implicitly convert expression (a2) of type immutable(S2) to S2 } //----
Jul 24 2013
parent Artur Skawina <art.08.09 gmail.com> writes:
On 07/24/13 12:54, monarch_dodra wrote:
 On Wednesday, 24 July 2013 at 10:37:40 UTC, Artur Skawina wrote:
 On 07/24/13 12:09, monarch_dodra wrote:
 Keeping it to "same type, 100% of the time" seems like the best.
No, it's a design bug. The head qualifier(s) should always be stripped when copying objects. Stripping is always fine (ie safe)
Nope. Stop. Wrong. Qualification is transitive in D, unlike in C++. Even when copying, stripping qualification is not safe:
"*Head* qualifier(s)". Why do I always end up quoting myself? ;) Obviously, stripping is only fine for the copied object itself, not for any internal refs. const(int*) cpci; auto mpci = cast()cpci; // const(int)* Unqual!(typeof(cpci)) mpci2; // const(int)* This works already; it's just that having to drop the qualifiers explicitly is unnecessary and bug-prone (it's too easy to cast away a bit too much const). artur
Jul 24 2013
prev sibling next sibling parent "MGW" <mgw yandex.ru> writes:
On Wednesday, 24 July 2013 at 08:07:55 UTC, Alex H wrote:
 This code:

 void test(const int n)
 {
 	auto j = n;
 	j++;
 }

 Gives this error:
 cannot modify const expression j


 Is this considered a feature or a bug? I would assume most 
 people
 wouldn't want new variables inheriting const.
There is no error. All right. auto - the type expects the maximum transfer of properties from the context. int j = n; j++ // if change j
Jul 24 2013
prev sibling next sibling parent reply "Mike Parker" <aldacron gmail.com> writes:
On Wednesday, 24 July 2013 at 08:07:55 UTC, Alex H wrote:
 This code:

 void test(const int n)
 {
 	auto j = n;
 	j++;
 }

 Gives this error:
 cannot modify const expression j


 Is this considered a feature or a bug? I would assume most 
 people
 wouldn't want new variables inheriting const.
This is the exact behavior I would expect. I think of auto as "this variable is going to be the same type as that variable." Since in is const int, then j also is going to be const int. If you want to copy n into a nonconst variable, you have to cast away the const. int j = cast( int )n; auto j = cast( int )n;
Jul 24 2013
next sibling parent "bsd" <slackovsky gmail.com> writes:
On Wednesday, 24 July 2013 at 11:26:32 UTC, Mike Parker wrote:
...
 This is the exact behavior I would expect. I think of auto as 
 "this variable is going to be the same type as that variable." 
 Since in is const int, then j also is going to be const int. If 
 you want to copy n into a nonconst variable, you have to cast 
 away the const.

 int j = cast( int )n;
 auto j = cast( int )n;
+1 This works fine for pods, no cast required int j = n; ++j; ...and this does what one would expect too struct S { int* value; } void funky(const S s) { int* s1 = s.value; *s1 = 5; } /d535/f466.d(9): Error: cannot implicitly convert expression (s.value) of type const(int*) to int* void funky(const S s) { S s1 = s; *s1.value = 5; } /d297/f947.d(9): Error: cannot implicitly convert expression (s) of type const(S) to S
Jul 24 2013
prev sibling parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 24 July 2013 at 11:26:32 UTC, Mike Parker wrote:
 This is the exact behavior I would expect. I think of auto as 
 "this variable is going to be the same type as that variable." 
 Since in is const int, then j also is going to be const int. If 
 you want to copy n into a nonconst variable, you have to cast 
 away the const.

 int j = cast( int )n;
 auto j = cast( int )n;
Casting is always an extreme measure, one that should be avoided in mundane code as much as possible. Despite the fact `auto` behaves as it should, this really highlights lack of `mutable` attribute in language.
Jul 25 2013
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, July 24, 2013 10:07:54 Alex H wrote:
 This code:
 
 void test(const int n)
 {
 auto j = n;
 j++;
 }
 
 Gives this error:
 cannot modify const expression j
 
 
 Is this considered a feature or a bug? I would assume most people
 wouldn't want new variables inheriting const.
The behavior is correct and desirable. It would be a big problem for generic code if the type of auto didn't match the right-hand side of the expression. In some cases, it might be okay if auto gave you the tail-const type, but even that could be problematic depending on the type. - Jonathan M Davis
Jul 24 2013