Jump to page: 1 2
Thread overview
Structs with pointers?
Jan 22, 2011
Sean Eskapp
Jan 22, 2011
bearophile
Jan 22, 2011
Sean Eskapp
Jan 22, 2011
bearophile
Jan 22, 2011
Sean Eskapp
Jan 22, 2011
bearophile
Jan 23, 2011
Dmitry Olshansky
Jan 23, 2011
bearophile
Jan 23, 2011
Mafi
Jan 23, 2011
Dmitry Olshansky
Jan 24, 2011
Dan Olson
January 22, 2011
Why doesn't this code work?

struct Bar
{
	int* x;
}

void foo(Bar a) {}

void main()
{
	const a = Bar();
	foo(a);
}

But replacing int* with some other type works fine? Even if a write a postblit function for Bar, it still fails to compile.
January 22, 2011
Sean Eskapp:

> Why doesn't this code work?

This works, the Bar instance you give to foo is const.

void foo(const Bar a) {}

Bye,
bearophile
January 22, 2011
== Quote from Sean Eskapp (eatingstaples@gmail.com)'s article
> Why doesn't this code work?
> struct Bar
> {
> 	int* x;
> }
> void foo(Bar a) {}
> void main()
> {
> 	const a = Bar();
> 	foo(a);
> }
> But replacing int* with some other type works fine? Even if a write a postblit
> function for Bar, it still fails to compile.

Nevermind, I realized it's because constness is transitive in pointers. A const struct with a pointer member has a const pointer member, and those can't be implicitly cast to non-const pointer members.
January 22, 2011
Sean Eskapp:

> Nevermind, I realized it's because constness is transitive in pointers. A const struct with a pointer member has a const pointer member, and those can't be implicitly cast to non-const pointer members.

Uhm, the struct having a pointer is not important. In theory this too can't compile:

struct Bar {}

void foo(Bar b) {}

void main() {
    const b = Bar();
    foo(b);
}

Is this another compiler bug?

Bye,
bearophile
January 22, 2011
== Quote from bearophile (bearophileHUGS@lycos.com)'s article
> Sean Eskapp:
> > Nevermind, I realized it's because constness is transitive in pointers. A const struct with a pointer member has a const pointer member, and those can't be implicitly cast to non-const pointer members.
> Uhm, the struct having a pointer is not important. In theory this too can't compile:
> struct Bar {}
> void foo(Bar b) {}
> void main() {
>     const b = Bar();
>     foo(b);
> }
> Is this another compiler bug?
> Bye,
> bearophile

No, that compiles fine. Because the struct owns a pointer, the const struct owns a const pointer. When copying a const-struct to a non-const struct, this means you must cast a const-pointer to a non-const pointer, which shouldn't be allowed.
January 22, 2011
> Is this another compiler bug?

The situation is nice:

struct Foo1 {}
struct Foo2 { int x; }
const struct Foo3 { int* p; }
struct Foo4 { int* p; }
void bar1(Foo1 f) {}
void bar2(Foo2 f) {}
void bar3(Foo3 f) {}
void bar4(Foo4 f) {}
void main() {
    const f1 = Foo1();
    bar1(f1); // no error
    const f2 = Foo2();
    bar2(f2); // no error
    const f3 = Foo3();
    bar3(f3); // no error
    const f4 = Foo4();
    bar4(f4); // error
}

Bye,
bearophile
January 23, 2011
On 23.01.2011 2:02, bearophile wrote:
>> Is this another compiler bug?
> The situation is nice:
>
> struct Foo1 {}
> struct Foo2 { int x; }
> const struct Foo3 { int* p; }
> struct Foo4 { int* p; }
> void bar1(Foo1 f) {}
> void bar2(Foo2 f) {}
> void bar3(Foo3 f) {}
> void bar4(Foo4 f) {}
> void main() {
>      const f1 = Foo1();
>      bar1(f1); // no error
>      const f2 = Foo2();
>      bar2(f2); // no error
>      const f3 = Foo3();
>      bar3(f3); // no error
>      const f4 = Foo4();
>      bar4(f4); // error
> }
>
> Bye,
> bearophile

The first two are actually OK, since you pass a copy of a value type FooX to barX.
If signature was void bar(ref FooX) then it should have failed.
But the third makes me wonder what the *** is going on.

-- 
Dmitry Olshansky

January 23, 2011
Dmitry Olshansky:

> The first two are actually OK, since you pass a copy of a value type
> FooX to barX.
> If signature was void bar(ref FooX) then it should have failed.
> But the third makes me wonder what the *** is going on.

I have added the third case to this bug report of mine: http://d.puremagic.com/issues/show_bug.cgi?id=3934

Bye,
bearophile
January 23, 2011
Am 23.01.2011 11:00, schrieb Dmitry Olshansky:
> On 23.01.2011 2:02, bearophile wrote:
>>> Is this another compiler bug?
>> The situation is nice:
>>
>> struct Foo1 {}
>> struct Foo2 { int x; }
>> const struct Foo3 { int* p; }
>> struct Foo4 { int* p; }
>> void bar1(Foo1 f) {}
>> void bar2(Foo2 f) {}
>> void bar3(Foo3 f) {}
>> void bar4(Foo4 f) {}
>> void main() {
>> const f1 = Foo1();
>> bar1(f1); // no error
>> const f2 = Foo2();
>> bar2(f2); // no error
>> const f3 = Foo3();
>> bar3(f3); // no error
>> const f4 = Foo4();
>> bar4(f4); // error
>> }
>>
>> Bye,
>> bearophile
>
> The first two are actually OK, since you pass a copy of a value type
> FooX to barX.
> If signature was void bar(ref FooX) then it should have failed.
> But the third makes me wonder what the *** is going on.
>

I think it's absolutely correct. Look: Foo3 is declared as const struct meaning all it's members are const. We are passing a struct like that to bar3:
 const Foo3 { const int* p}
which is implicitely converted to:
 Foo3 { const int* p } //not ref !!
Because it's not ref you can't manipulate the original struct anyways and the pointer is still const. As long as you don't cast you cannot change what the pointer points to so this implicit conversion is correct IMO.
It's like const(T[]) => const(T)[] .

Mafi
January 23, 2011
On 23.01.2011 19:05, Mafi wrote:
> Am 23.01.2011 11:00, schrieb Dmitry Olshansky:
>> On 23.01.2011 2:02, bearophile wrote:
>>>> Is this another compiler bug?
>>> The situation is nice:
>>>
>>> struct Foo1 {}
>>> struct Foo2 { int x; }
>>> const struct Foo3 { int* p; }
>>> struct Foo4 { int* p; }
>>> void bar1(Foo1 f) {}
>>> void bar2(Foo2 f) {}
>>> void bar3(Foo3 f) {}
>>> void bar4(Foo4 f) {}
>>> void main() {
>>> const f1 = Foo1();
>>> bar1(f1); // no error
>>> const f2 = Foo2();
>>> bar2(f2); // no error
>>> const f3 = Foo3();
>>> bar3(f3); // no error
>>> const f4 = Foo4();
>>> bar4(f4); // error
>>> }
>>>
>>> Bye,
>>> bearophile
>>
>> The first two are actually OK, since you pass a copy of a value type
>> FooX to barX.
>> If signature was void bar(ref FooX) then it should have failed.
>> But the third makes me wonder what the *** is going on.
>>
>
> I think it's absolutely correct. Look: Foo3 is declared as const struct meaning all it's members are const. We are passing a struct like that to bar3:
>  const Foo3 { const int* p}
> which is implicitely converted to:
>  Foo3 { const int* p } //not ref !!
> Because it's not ref you can't manipulate the original struct anyways and the pointer is still const. As long as you don't cast you cannot change what the pointer points to so this implicit conversion is correct IMO.
> It's like const(T[]) => const(T)[] .
Right, that makes sense.
But do we really need this syntax: const struct { ... }  ?
>
> Mafi

-- 

Dmitry Olshansky

« First   ‹ Prev
1 2