Re: Why is it not possible to write to a file from a const member function ?
On Saturday, 12 March 2016 at 15:32:39 UTC, Mike Parker wrote: On Saturday, 12 March 2016 at 14:02:31 UTC, user42 wrote: Why is this thing not compiling ? Or, in other words, how is is possible to log something to a file from a const member function ? Const member functions functions are not allowed to mutate any member state at all. This includes the state of any object instances that are members. Since the write method of the File type is not declared as const, then you can not call it on a member of type File from inside a const member function. Logging, by its very definition, mutates state. Move the File instance outside of the class and it works. import std.stdio; private File f; static this() { f = stdout; } class X { void p(string s) const { f.writeln!(string)(s); } } class Y { private string s = "Y"; override string toString() const { return s; } } void main() { auto x = new X; auto y = new Y; import std.conv: to; x.p(to!string(y)); } Thanks for your reply. Unfortunately it only solves the problem for this particular snippet. The most interesting part of your reply is this line: Since the write method of the File type is not declared as const, At a quick glance I suppose it's because of the locking in LockingTextWriter. I think I will probably pass this stuff to a C implementation, or override toString non-const, since adding const to it started this const avalanche in the first place. Anyways, thanks for your input and have a nice weekend.
Re: Why is it not possible to write to a file from a const member function ?
On Saturday, 12 March 2016 at 14:02:31 UTC, user42 wrote: Why is this thing not compiling ? Or, in other words, how is is possible to log something to a file from a const member function ? Const member functions functions are not allowed to mutate any member state at all. This includes the state of any object instances that are members. Since the write method of the File type is not declared as const, then you can not call it on a member of type File from inside a const member function. Logging, by its very definition, mutates state. Move the File instance outside of the class and it works. import std.stdio; private File f; static this() { f = stdout; } class X { void p(string s) const { f.writeln!(string)(s); } } class Y { private string s = "Y"; override string toString() const { return s; } } void main() { auto x = new X; auto y = new Y; import std.conv: to; x.p(to!string(y)); }
Why is it not possible to write to a file from a const member function ?
Hi I have the following snippet to illustrate my problem/question: class X { import std.stdio: write, File, stdout; private File* f = &stdout; void p(string s) const { f.write(s); } } class Y { private string s = "Y"; override string toString() const { return s; } } void main() { auto x = new X; auto y = new Y; import std.conv: to; x.p(to!string(y)); } Why is this thing not compiling ? Or, in other words, how is is possible to log something to a file from a const member function ? Thanks in advance
Re: const member function
On Monday, February 23, 2015 09:12:33 rumbu via Digitalmars-d-learn wrote: > On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote: > > On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote: > > > >> My question was not how I do this, I know already. My question > >> was if > >> there is another way to safely call a non-const instance > >> function on a > >> const object. > > > > is there a way to been safely hit by a truck? > > I thought if there is some language construct similar to @trusted > for @safe, applicable to const member functions. You can be > safely hit by a truck if I tell you that there is no truck around > :) No. That wouldn't work at all because of immutable. A const method can be called on an immutable variable just as well as it can be called on a const or mutable one. In addition to that, Walter Bright feels very strongly that const should provide actual compiler guarantees, and when you have something like C++'s mutable which gives you a backdoor on const, the compiler can't really guarantee much of anything. @trusted has similar problems in that the programmer can screw it up and mark stuff as @trusted which makes the calling code unsafe, but that would be an actual bug in the program, whereas C++s mutable isn't a bug. Mutating const is perfectly acceptle in C++. It just doesn't work unless you tell the compiler to let you do it anyway, and the behavior is well-defined, whereas doing anything like casting away const and mutating a variable in D is undefined behavior, because the compiler is free to rely on const variables not changing so long as it can guarantee that a mutable reference to the same data can't have mutated that data. And yes, on some level, that sucks, because stuff like caching doesn't work with const, but it does mean that you can rely on const actually being const, which does provide other benefits. It does take some getting used to though. Regardless, the fact that we have immutable pretty much forces the issue - especially when you consider that the compiler can choose to put immutable variables in read-only-memory if it thinks that makes sense. - Jonathan M Davis
Re: const member function
On Mon, 23 Feb 2015 09:12:33 +, rumbu wrote: > On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote: >> On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote: >> >>> My question was not how I do this, I know already. My question was if >>> there is another way to safely call a non-const instance function on a >>> const object. >> >> is there a way to been safely hit by a truck? > > I thought if there is some language construct similar to @trusted for > @safe, applicable to const member functions. You can be safely hit by a > truck if I tell you that there is no truck around :) do not make it `const` at all. i see something very strange in making something `const` just to find the way to remove constness. just stop writing C++ code in D. signature.asc Description: PGP signature
Re: const member function
On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote: On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote: My question was not how I do this, I know already. My question was if there is another way to safely call a non-const instance function on a const object. is there a way to been safely hit by a truck? I thought if there is some language construct similar to @trusted for @safe, applicable to const member functions. You can be safely hit by a truck if I tell you that there is no truck around :)
Re: const member function
On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote: On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote: My question was not how I do this, I know already. My question was if there is another way to safely call a non-const instance function on a const object. is there a way to been safely hit by a truck? In a tank. ;)
Re: const member function
On Saturday, 21 February 2015 at 06:38:18 UTC, rumbu wrote: Often I'm using the following code pattern: class S { private SomeType cache; public SomeType SomeProp() @property { if (cache is null) cache = SomeExpensiveOperation(); return cache; } } Is there any way to mark SomeProp() as const? Because I want to call somewhere const(S).SomeProp, which for the outside world is must be "const", returning just a value, even that internaly it modifies the internal S structure. AFAIK it is unsafe and not recommended, but this works for me: import std.stdio; class Foo { void say(string s) const { writeln(s); } } class Bar { Foo f; const(Foo) getFoo() const { if (!f) cast() this.f = new Foo(); return f; } } void main() { Bar b = new Bar(); const Foo f = b.getFoo(); f.say("Hello"); }
Re: const member function
On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote: > My question was not how I do this, I know already. My question was if > there is another way to safely call a non-const instance function on a > const object. is there a way to been safely hit by a truck? signature.asc Description: PGP signature
Re: const member function
On Saturday, February 21, 2015 08:27:13 rumbu via Digitalmars-d-learn wrote: > On Saturday, 21 February 2015 at 08:08:25 UTC, Mike Parker wrote: > > On 2/21/2015 4:31 PM, rumbu wrote: > > > > you can do this instead: > > > > this() { cache = SomeExpensiveOp(); } > > > > public @property const(int) SomeProp() const > > { > > return cache; > > } > > > > Notice the const on the end of SomeProp. That makes the > > function callable on a const instance, but you still cannot > > modify cache inside of it. > > My question was not how I do this, I know already. My question > was if there is another way to safely call a non-const instance > function on a const object. > > Initializing "cache" in the constructor will defeat the cache > mechanism itself an that's I want to avoid. Nope. If you want to use caching, you can't do it with const. D's const is transitive, and it's not logical const. It's physical const. If _any_ portion of an object were to be mutated by a const function, it would violate the type system. Unlike C++'s const, D's const provides actual guarantees about the data not changing, which can be useful for some optimizations but is outright required because of immutable. For instance, imagine if your object were immutable and your const function were somehow able to mutate on of the object's members (e.g. by casting away const). An immutable object could be in read-only-memory, in which case, that would segfault. And even if it didn't, it could cause really weird bugs due to the fact that the compiler is free to assume that an immutable object never changes and that an object can never be mutated via a const reference. The fact that immutable objects are implicitly shared would make it even worse, because then you'd risk thread-related issues to boot. The reality of the matter is that if you want to do any kind of caching like this, you either have to do the caching only in mutable functions (in which case, the const function could take advantage of the cached value if it were there but would have to calculate it if it hadn't been cached already), or you can't do caching at all. Ultimately, for better or worse, D's const is a very different beast from C++'s const, and you can't approach them the same way. This SO question discusses the issue: http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis
Re: const member function
On Saturday, 21 February 2015 at 07:31:19 UTC, rumbu wrote: On Saturday, 21 February 2015 at 07:01:12 UTC, Baz wrote: --- class S { private SomeType cache; public const(SomeType) SomeProp() @property { if (cache is null) cache = SomeExpensiveOperation(); return cache; } } --- the result of the getter will be read-only My intention is not to have a read-only getter, I want to call SomeProp on a const object: class S { private int cache = -1; private int SomeExpensiveOp() { return 12345; } public @property const(int) SomeProp() { if (cache = -1) cache = SomeExpensiveOp(); return cache; } } unittest { const(S) s = new S(); auto i = s.SomeProp; //mutable method S.SomeProp is not callable using a const object } right, i have not carefully read the body of the Q. my bad.
Re: const member function
On Saturday, 21 February 2015 at 08:08:25 UTC, Mike Parker wrote: On 2/21/2015 4:31 PM, rumbu wrote: you can do this instead: this() { cache = SomeExpensiveOp(); } public @property const(int) SomeProp() const { return cache; } Notice the const on the end of SomeProp. That makes the function callable on a const instance, but you still cannot modify cache inside of it. My question was not how I do this, I know already. My question was if there is another way to safely call a non-const instance function on a const object. Initializing "cache" in the constructor will defeat the cache mechanism itself an that's I want to avoid.
Re: const member function
On 2/21/2015 4:31 PM, rumbu wrote: My intention is not to have a read-only getter, I want to call SomeProp on a const object: class S { private int cache = -1; private int SomeExpensiveOp() { return 12345; } public @property const(int) SomeProp() { if (cache = -1) cache = SomeExpensiveOp(); return cache; } } const is transitive. If an instance of S is const, then all of its members are const, too. You cannot modify cache in that case. Assuming cache only needs to be initialized once, you can do this instead: this() { cache = SomeExpensiveOp(); } public @property const(int) SomeProp() const { return cache; } Notice the const on the end of SomeProp. That makes the function callable on a const instance, but you still cannot modify cache inside of it.
Re: const member function
On Saturday, 21 February 2015 at 07:01:12 UTC, Baz wrote: --- class S { private SomeType cache; public const(SomeType) SomeProp() @property { if (cache is null) cache = SomeExpensiveOperation(); return cache; } } --- the result of the getter will be read-only My intention is not to have a read-only getter, I want to call SomeProp on a const object: class S { private int cache = -1; private int SomeExpensiveOp() { return 12345; } public @property const(int) SomeProp() { if (cache = -1) cache = SomeExpensiveOp(); return cache; } } unittest { const(S) s = new S(); auto i = s.SomeProp; //mutable method S.SomeProp is not callable using a const object }
Re: const member function
--- class S { private SomeType cache; public const(SomeType) SomeProp() @property { if (cache is null) cache = SomeExpensiveOperation(); return cache; } } --- the result of the getter will be read-only
const member function
Often I'm using the following code pattern: class S { private SomeType cache; public SomeType SomeProp() @property { if (cache is null) cache = SomeExpensiveOperation(); return cache; } } Is there any way to mark SomeProp() as const? Because I want to call somewhere const(S).SomeProp, which for the outside world is must be "const", returning just a value, even that internaly it modifies the internal S structure.