www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Translating C const

reply Jacob Carlborg <doob me.com> writes:
I'm trying to figuring out how to translate const in C to D. I have 
these examples:

const int * a;
int * const b;
const int * const c;
const int * const * d;

Which I think should be translated like this:

const(int)* a;
const int* c;
const(int*)* d;

But I don't know how to translate "b". I think "b" is a const pointer to 
a mutable int, is that possible to have in D?

-- 
/Jacob Carlborg
May 15 2012
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/15/2012 12:36 PM, Jacob Carlborg wrote:
 I'm trying to figuring out how to translate const in C to D. I have
 these examples:

 const int * a;
 int * const b;
 const int * const c;
 const int * const * d;

 Which I think should be translated like this:

 const(int)* a;
 const int* c;
 const(int*)* d;

 But I don't know how to translate "b". I think "b" is a const pointer to
 a mutable int, is that possible to have in D?

Not possible in D. D's const is transitive. If b is const, then what it points to is also const. Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
May 15 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-15 21:50, Ali Çehreli wrote:

 Not possible in D. D's const is transitive. If b is const, then what it
 points to is also const.

 Ali

Then it would be best to not declare that as const? -- /Jacob Carlborg
May 15 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-16 07:35, Simen Kjaeraas wrote:

 That depends. Will the contents be modified?

I have no idea. I'm working on a tool for automatically translating C headers. I was thinking since I don't know, I better not add any promises that is not kept. -- /Jacob Carlborg
May 15 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-16 09:00, Jonathan M Davis wrote:

 Probably true. But also, if you're talking about a const pointer to a mutable
 value, the constness of the pointer is actually irrelevant to the caller. The
 pointer will be copied when the function is called, so it doesn't matter on
 whit whether the pointer itself is const or not. What matters is whether
 what's being pointed to is const or not. So, if you have a function which
 takes a const pointer to a non-const value, then that's essentially identical
 to one that takes a non-const pointer to a non-const value as far as the
 declarations go - and for declaring extern(C) functions for use in D, that's
 generally all you care about.

 - Jonathan M Davis

Ok I see, thanks. Is that true for fields in structs and global variables as well? -- /Jacob Carlborg
May 16 2012
next sibling parent Simon <s.d.hammett gmail.com> writes:
On 16/05/2012 09:24, Jacob Carlborg wrote:
 On 2012-05-16 09:00, Jonathan M Davis wrote:

 Probably true. But also, if you're talking about a const pointer to a
 mutable
 value, the constness of the pointer is actually irrelevant to the
 caller. The
 pointer will be copied when the function is called, so it doesn't
 matter on
 whit whether the pointer itself is const or not. What matters is whether
 what's being pointed to is const or not. So, if you have a function which
 takes a const pointer to a non-const value, then that's essentially
 identical
 to one that takes a non-const pointer to a non-const value as far as the
 declarations go - and for declaring extern(C) functions for use in D,
 that's
 generally all you care about.

 - Jonathan M Davis

Ok I see, thanks. Is that true for fields in structs and global variables as well?

Yes. const pointer in c++ is some times used as short hand for saying that the pointer is not an array. i.e. you don't intend to increment the pointer or index through it. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
May 16 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-26 01:17, Jonathan M Davis wrote:

 Ok I see, thanks. Is that true for fields in structs and global
 variables as well?


 Anyway, I suppose that that's not terribly conclusive, but the lack of ability
 to have non-transitive const declarations is a bit of a problem when dealing
 with extern(C) functions given that it has behaviors that D _doesn't_ have. As
 far as I can see, whether constifying the whole thing or making it all mutable
 makes more sense really depends on what the C function is doing and how it's
 called, which naturally doesn't go well with a tool like you're creating.
 You'll probably have to go with what is _least_ likely to cause bugs and then
 let the programmer adjust it as needed.

 - Jonathan M Davis

What do you think about translating the C const to D where possible and then just leave it mutable in all other cases. Then assuming the C code will not cast away const. A user is always free to edit the bindings manually. -- /Jacob Carlborg
May 26 2012
parent Jacob Carlborg <doob me.com> writes:
 That seems like a good approach, since then you're not marking things as const
 in D that C would consider mutable and therefore be likely to be altered,
 breaking D's guarantees. It does make me think that it could be valuable to
 include a comment with the original declaration though (at least in cases
 where a direct translation isn't possible). That way, it would be clearer that
 the signature in D isn't quite right. e.g.

 /**
      Comment
    */
 extern(C) void func(int*const* param);

 becomes something like

 /**
      Comment
    */
 extern(C) void func(int** param);
 //orig: void func(int*const* param);

 - Jonathan M Davis

That might be a good idea. Thanks for your feedback. -- /Jacob Carlborg
May 27 2012
prev sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Tue, 15 May 2012 21:58:46 +0200, Jacob Carlborg <doob me.com> wrote:

 On 2012-05-15 21:50, Ali =C3=87ehreli wrote:

 Not possible in D. D's const is transitive. If b is const, then what =


 points to is also const.

 Ali

Then it would be best to not declare that as const?

That depends. Will the contents be modified?
May 15 2012
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, May 16, 2012 08:50:27 Jacob Carlborg wrote:
 On 2012-05-16 07:35, Simen Kjaeraas wrote:
 That depends. Will the contents be modified?

I have no idea. I'm working on a tool for automatically translating C headers. I was thinking since I don't know, I better not add any promises that is not kept.

Probably true. But also, if you're talking about a const pointer to a mutable value, the constness of the pointer is actually irrelevant to the caller. The pointer will be copied when the function is called, so it doesn't matter on whit whether the pointer itself is const or not. What matters is whether what's being pointed to is const or not. So, if you have a function which takes a const pointer to a non-const value, then that's essentially identical to one that takes a non-const pointer to a non-const value as far as the declarations go - and for declaring extern(C) functions for use in D, that's generally all you care about. - Jonathan M Davis
May 16 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, May 16, 2012 10:24:55 Jacob Carlborg wrote:
 On 2012-05-16 09:00, Jonathan M Davis wrote:
 Probably true. But also, if you're talking about a const pointer to a
 mutable value, the constness of the pointer is actually irrelevant to the
 caller. The pointer will be copied when the function is called, so it
 doesn't matter on whit whether the pointer itself is const or not. What
 matters is whether what's being pointed to is const or not. So, if you
 have a function which takes a const pointer to a non-const value, then
 that's essentially identical to one that takes a non-const pointer to a
 non-const value as far as the declarations go - and for declaring
 extern(C) functions for use in D, that's generally all you care about.
 
 - Jonathan M Davis

Ok I see, thanks. Is that true for fields in structs and global variables as well?

Well, the reason that it's not an issue at all with function parameters where it's the pointer which is const is that the const portion is being copied. With a struct being passed to a function as an argument, anything which is directly const in the struct doesn't have to stay const when passed (it's just the indirect stuff which would be - pointers and references - though having a reference as a member variable is a bit evil). However, if that same struct can be passed around via a pointer, then those member variables would have to be const. I'm not sure that it's possible to generically constify C structs for D correctly. If you just use D's const on const member variables, then you won't be able to mutate what's pointed to by pointers which were const but pointed to mutable data in the C definition. In many cases, that wouldn't be an issue at all, but depending on what you needed to do in D, it would be. On the other hand, if you just didn't use const at all, then you _could_ mutate what needed to be mutated, _and_ it would be perfectly legal per C, because it would be the equivalent of casting away const in C, but if the C stuff really did treat it as const, and the D code mutated it, that could cause bugs. Sadly, the most correct thing would probably be to error on the side of _not_ making extern(C) stuff const, because mutating what should have been const is legal in C (so not having it const in D and then mutating it wouldn't violate C's guarantees at all), whereas if you make it const, the D code is free to assume that the C code _isn't_ going to mutate it, and since the C code _can_ cast away const (or may be dealing with non-transitive const such that it can legally mutate some of the object), then making it const when C doesn't consider it const could result in D incorrectly optimizing stuff. Of course, since C can always cast away const regardless, having D call _any_ C functions which use const stuff (even if it's transitively const in C as well) could result in const stuff being mutated. However, if D were to just assume that const optimizations can't be done when dealing with extern(C) functions (I don't know if it does or not), then using const more heavily wouldn't be as big a deal. Anyway, I suppose that that's not terribly conclusive, but the lack of ability to have non-transitive const declarations is a bit of a problem when dealing with extern(C) functions given that it has behaviors that D _doesn't_ have. As far as I can see, whether constifying the whole thing or making it all mutable makes more sense really depends on what the C function is doing and how it's called, which naturally doesn't go well with a tool like you're creating. You'll probably have to go with what is _least_ likely to cause bugs and then let the programmer adjust it as needed. - Jonathan M Davis
May 25 2012
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, May 26, 2012 13:05:00 Jacob Carlborg wrote:
 On 2012-05-26 01:17, Jonathan M Davis wrote:
 Ok I see, thanks. Is that true for fields in structs and global
 variables as well?

Anyway, I suppose that that's not terribly conclusive, but the lack of ability to have non-transitive const declarations is a bit of a problem when dealing with extern(C) functions given that it has behaviors that D _doesn't_ have. As far as I can see, whether constifying the whole thing or making it all mutable makes more sense really depends on what the C function is doing and how it's called, which naturally doesn't go well with a tool like you're creating. You'll probably have to go with what is _least_ likely to cause bugs and then let the programmer adjust it as needed. - Jonathan M Davis

What do you think about translating the C const to D where possible and then just leave it mutable in all other cases. Then assuming the C code will not cast away const. A user is always free to edit the bindings manually.

That seems like a good approach, since then you're not marking things as const in D that C would consider mutable and therefore be likely to be altered, breaking D's guarantees. It does make me think that it could be valuable to include a comment with the original declaration though (at least in cases where a direct translation isn't possible). That way, it would be clearer that the signature in D isn't quite right. e.g. /** Comment */ extern(C) void func(int*const* param); becomes something like /** Comment */ extern(C) void func(int** param); //orig: void func(int*const* param); - Jonathan M Davis
May 26 2012