| Thread overview | |||||||||
|---|---|---|---|---|---|---|---|---|---|
|
January 06, 2008 Struct initializers and const in 2.009 | ||||
|---|---|---|---|---|
| ||||
---
struct Foo
{
int val;
}
struct Bar {
Foo f;
//const Foo f; // workaround
}
const Foo foo = { 123 }; // line 11
const Bar bar = {
f: foo // the problem is here
};
---
bug.d(11): Error: cannot implicitly convert expression (Foo(123)) of type const(Foo) to Foo
The problem here is that Bar.f is not const, while foo is. Since bar is const, shouldn't consts always be legal in the initializer? Or doesn't it work that way?
The workaround for this is pretty simple, I know. foo could also be made an enum, but I need 1.x compatibility.
| ||||
January 06, 2008 Re: Struct initializers and const in 2.009 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to torhu | torhu wrote:
> ---
> struct Foo
> {
> int val;
> }
>
> struct Bar {
> Foo f;
> //const Foo f; // workaround
> }
>
> const Foo foo = { 123 }; // line 11
>
> const Bar bar = {
> f: foo // the problem is here
> };
> ---
> bug.d(11): Error: cannot implicitly convert expression (Foo(123)) of type const(Foo) to Foo
>
> The problem here is that Bar.f is not const, while foo is. Since bar is const, shouldn't consts always be legal in the initializer? Or doesn't it work that way?
>
> The workaround for this is pretty simple, I know. foo could also be made an enum, but I need 1.x compatibility.
Weird. With transitive const, I'd expect the assignment to be from const(Foo) to const(Foo).
Sean
| |||
January 06, 2008 Re: Struct initializers and const in 2.009 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to torhu | Another surprise I got was when doing something like this:
---
struct Bar {
int f;
}
const Bar bar = { 5 };
void f(in Bar b)
{
Bar[3] array;
array[0] = b; // line 10
//array[0] = *cast(Bar*)&b; // ugly workaround
}
void main()
{
f(bar);
}
---
bug2.d(10): Error: cannot implicitly convert expression (b) of type const(Bar) to Bar
The problem here is that f's parameter has to be 'in' or 'const', otherwise bar can't be used as an argument to f. But a const Bar can't be assigned to an element of an array, since the elements cannot be const, or assigning to them would be disallowed.
So I guess mixing const and mutable structs is no longer viable as of 2.009, they would have to be separate types. But I guess that's the way transitive const has to be. In this example, making bar an enum instead of a const would solve the issue, though. I'm only doing this because I'm looking for an 1.0 compatible way of declaring struct consts like bar. Maybe I should just remove const instead.
Trying to cast away the constness of f's b argument doesn't work either. The compiler complains about a missing opCall when I do 'cast(Bar)b'. Is that bug, or is a different syntax for casting away const needed?
| |||
January 07, 2008 Re: Struct initializers and const in 2.009 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to torhu |
You actually managed to make your programs compatible with D 1.x and 2.x !?!?
I spent a good 40 minutes on my source, and ultimately realized it's impossible for me to do so;
version(D_Version2)
alias const(char)[] const_string;
else
alias char[] const_string;
Value {
const Value opIndex(const_string){
bla bla
}
}
You can't alias out the const declaration for the function, and you can't get rid of it in 2.x and still have the program work, let alone have the desired functionality.
Only reason the strings work is 'cause Alan showed me. : )
| |||
January 07, 2008 Re: Struct initializers and const in 2.009 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Dan | Dan wrote: > You actually managed to make your programs compatible with D 1.x and 2.x !?!? Only some bindings to a C library, so no classes or const methods necessary. > I spent a good 40 minutes on my source, and ultimately realized it's impossible for me to do so; > > version(D_Version2) > alias const(char)[] const_string; > else > alias char[] const_string; > > Value { > const Value opIndex(const_string){ > bla bla } > } > > You can't alias out the const declaration for the function, and you can't get rid of it in 2.x and still have the program work, let alone have the desired functionality. Maybe you could make it work with some casting, but it might not be worth it. The const_string alias will work if you use a string mixin: version(D_Version2) mixin("alias const(char)[] const_string;"); else alias char[] const_string; But are you sure you need this, won't the Phobos string alias work? It's defined in object.d. | |||
January 07, 2008 Re: Struct initializers and const in 2.009 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to torhu | torhu wrote:
> Dan wrote:
>> You actually managed to make your programs compatible with D 1.x and 2.x !?!?
>
> Only some bindings to a C library, so no classes or const methods necessary.
>
>> I spent a good 40 minutes on my source, and ultimately realized it's impossible for me to do so;
>>
>> version(D_Version2)
>> alias const(char)[] const_string;
>> else
>> alias char[] const_string;
>>
>> Value {
>> const Value opIndex(const_string){
>> bla bla }
>> }
>>
>> You can't alias out the const declaration for the function, and you can't get rid of it in 2.x and still have the program work, let alone have the desired functionality.
>
> Maybe you could make it work with some casting, but it might not be worth it. The const_string alias will work if you use a string mixin:
>
> version(D_Version2)
> mixin("alias const(char)[] const_string;");
> else
> alias char[] const_string;
>
> But are you sure you need this, won't the Phobos string alias work? It's defined in object.d.
And then you can just do:
static if (!is(typeof(string))) alias char[] string;
Future-proofs in case your code works with Tango and it gets a string alias in the future.
| |||
January 07, 2008 Re: Struct initializers and const in 2.009 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to torhu | torhu wrote:
> Dan wrote:
>> You actually managed to make your programs compatible with D 1.x and 2.x !?!?
>
> Only some bindings to a C library, so no classes or const methods necessary.
>
>> I spent a good 40 minutes on my source, and ultimately realized it's impossible for me to do so;
>>
>> version(D_Version2)
>> alias const(char)[] const_string;
>> else
>> alias char[] const_string;
>>
>> Value {
>> const Value opIndex(const_string){
>> bla bla }
>> }
>>
>> You can't alias out the const declaration for the function, and you can't get rid of it in 2.x and still have the program work, let alone have the desired functionality.
>
> Maybe you could make it work with some casting, but it might not be worth it. The const_string alias will work if you use a string mixin:
>
> version(D_Version2)
> mixin("alias const(char)[] const_string;");
> else
> alias char[] const_string;
>
> But are you sure you need this, won't the Phobos string alias work? It's defined in object.d.
You don't need either one for the function parameter. Try this:
... opIndex( in char[] ) {}
I've come to the conclusion that the string aliases are really of fairly little utility in D, since 'in' works just as well for specifying const behavior and is also 1.0 compatible. About the only place I've found myself using them for portable code is the return value of the toString routine, since there is no portable way to define a const return value other than an alias with string mixins, as above.
Sean
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply