logical const is a subset of transitive const
Steven Schveighoffer
schveiguy at yahoo.com
Fri Sep 14 13:44:32 PDT 2007
"Bill Baxter" wrote
> Janice Caron wrote:
>> On 9/14/07, Steven Schveighoffer <schveiguy at yahoo.com> wrote:
>>> I disagree. Declaring it const means that calling that function will
>>> not
>>> change any members of the date object.
>>>
>>> Declaring it pure means that it will always return the same value, which
>>> means it would be safe for multiple threads to access without locking (I
>>> am
>>> very new to this concept, but I got all my knowledge from wikipedia:
>>> http://en.wikipedia.org/wiki/Functional_programming)
>>
>> I stand corrected. Yes, you are right. A function can be declared
>> const and still read and write global variables, and hence not be
>> threadsafe.
>
> Whoa. Excuse me while I get up off the floor after having the rug pulled
> out from under me.
>
> Was the point of const then perhaps more micro-level optimizations? Things
> like if "X is const then I can assume the value in this register is still
> valid without having to re-fetch from main memory". For instance
> X* foo;
> foo.bar = 10;
> func(foo); // takes fully_const X*
>
> // In C++ const the next line requires re-fetching foo.bar
> // from memory,
> // because func might actually change fully_const X*.
> // In D it could reuse the value in register, or even assume it's
> // still the constant 10.
>
> Y biff = foo.bar;
>
> Just a guess. IANACW (compiler writer).
IAANACW (I am also not a compiler writer).
You are wrong in your assumption. Even in a single thread, I can circumvent
the constness by having a global non-const pointer to my object, and using
that object. Very bad implementation, but it would not break the rules.
For example:
X mutableinstance;
class X
{
int bar;
}
func(const X myref)
{
mutableinstance.bar++; // I can do this because I'm not changing myref
}
myfoolishfunc()
{
X foo = new X;
mutableinstance = foo;
foo.bar = 10;
func(foo); // increments foo.bar because mutableinstance is foo
int biff = foo.bar; // biff now should be 11.
}
The definition of a function that does not have ANY side effects is a pure
function (see the functional programming reference). That type of function
would not be able to change anything, even global variables, and so the
compiler could assume that bar still contained 10 (BTW you cannot assume
the register is still valid after calling func because func is allowed to
change registers, even if it is pure).
However, in multithreaded land, it is questionable whether you can assume
that foo will not change even with pure functions because another thread
could conceivably come along and wreck foo while you are calling your pure
function.
Multithreaded programming is hard. const sucks. There are a lot of strange
rules. Not being a compiler writer, I have no idea what compiler advantages
transitive const has over logical const, but I'm going to defer to Walter on
that because he is the compiler writer, and he seems to be very hard-set on
it. However, being an OO programmer and designer, and having lots of
experience with threading, I want to ensure that the compiler optimizations
are not going to impede the language as a good OO-equiped language. I hope
with my proposal, that both sides are satisfied.
-Steve
More information about the Digitalmars-d
mailing list