digitalmars.D - const(Class) is mangled as Class const* const
- Benjamin Thaut (36/36) Mar 26 2017 Consider the following C++ and D source:
- deadalnix (7/10) Mar 26 2017 It's consistent. D's const is transitive, and D doesn't allow you
- Namespace (7/17) Mar 26 2017 After reading your post, I wonder: How could I translate the
- Jonathan M Davis via Digitalmars-d (17/36) Mar 26 2017 You don't. Once part of a type is const, everything inside it is const. ...
- Jerry (12/19) Mar 26 2017 There are quite a few things wrong with const, it's so bad phobos
- Jonathan M Davis via Digitalmars-d (67/86) Mar 26 2017 There are significant pros and cons when comparing C++ and D's const, bu...
- Benjamin Thaut (7/11) Mar 26 2017 I disagree. When binding C++ code to D I don't care about D's
- deadalnix (9/21) Mar 26 2017 It is clear that you won't be able to express 100% of C++ in D,
- Jerry (16/24) Mar 26 2017 For `const Class*` the Class is not mutable. It is the case of
- deadalnix (3/16) Mar 27 2017 You are correct. See my first post for an explanation of this
- Walter Bright (5/9) Mar 27 2017 Ironically, because C++ const is not transitive, most programmers use co...
- kinke (18/22) Mar 27 2017 I agree that C++-mangling a const D object reference as `const T
- Walter Bright (10/11) Mar 27 2017 It's not a bug, it was intended that way.
- kinke (8/16) Mar 27 2017 Unfortunately, it's almost always the other way around - D code
- Walter Bright (4/10) Mar 27 2017 It's made to work with:
- kinke (4/19) Mar 27 2017 Okay, so how exactly do I bind D code to a C++
- Walter Bright (2/9) Mar 27 2017 C++ templates are always header-only. I don't really understand your que...
- kinke (4/17) Mar 27 2017 Yep, so there are no libs my D code can link to, so how am I
- Walter Bright (3/18) Mar 27 2017 There's still a miscommunication here, as header-only template libraries...
- Jacob Carlborg (6/9) Mar 28 2017 As far as I understand, D can link with C++ templates if they're
- Walter Bright (3/5) Mar 28 2017 Recall that dmd itself connected to C++ templates when the front end was...
- Jonathan M Davis via Digitalmars-d (35/51) Mar 27 2017 Realistically, unless D fully supports C++ (which pretty much means that...
- kinke (17/25) Mar 28 2017 I know that. I'm just arguing for this tiny change in
- Nathan S. (5/21) Aug 25 2020 I just ran into this problem too. Is there some way around this
- Nathan S. (6/8) Aug 26 2020 For anyone else wondering: it turns out yes, pragma(mangle) works
- Walter Bright (2/3) Aug 26 2020 https://issues.dlang.org/show_bug.cgi?id=21200
Consider the following C++ and D source: class Class { virtual ~Class(){} }; // mangles as ?getClass YAPEAVClass XZ Class * getClass() { return nullptr; } // mangles as ?getClassConst YAPEBVClass XZ const Class * getClassConst() { return nullptr; } // mangles as ?getClassConstConst YAQEBVClass XZ const Class * const getClassConstConst() { return nullptr; } extern(C++) { class Class { void _cppDtor() {} } // Mangles as ?getClass YAPEAVClass XZ Class getClass() {return null;} // Mangles as ?getClassConst YAQEBVClass XZ const(Class) getClassConst() {return null;} } As you see from the above example D mangles the getClassConst as a "Class const * const" instead of a "Class const *" ("YAQEBV" vs "YAPEBV"). Is this expected behavior? The core problem is that D can not express one of the two. Either const(Class) becomes "Class const *" or "Class const * const". I've never seen C++ code that returns const pointers to const classes so I think the default should be "Class const *". Either way its rather bad that we can only represent one or the other. Sooner or later someone will hit this problem again wanting the other option or both. Any idea how we can avoid changing C++ source code in order to bind it to D? Using pragma(mangle,) works but is kind of ugly. Especially because the string to pragma(mangle,) can't be genearted using CTFE. Should I open a bug for this?
Mar 26 2017
On Sunday, 26 March 2017 at 10:43:11 UTC, Benjamin Thaut wrote:As you see from the above example D mangles the getClassConst as a "Class const * const" instead of a "Class const *" ("YAQEBV" vs "YAPEBV"). Is this expected behavior?It's consistent. D's const is transitive, and D doesn't allow you to specify const on the indirection of a reference type. So there is no problem on the C++ mangling side of things, but, arguably, there is one in D's sementic, that isn't new. Something like differentiating "const(C) i" and "const C i" may be a good idea.
Mar 26 2017
On Sunday, 26 March 2017 at 14:30:00 UTC, deadalnix wrote:On Sunday, 26 March 2017 at 10:43:11 UTC, Benjamin Thaut wrote:After reading your post, I wonder: How could I translate the following C++ code to D? ---- int a = 2; int* const p = &a; ----As you see from the above example D mangles the getClassConst as a "Class const * const" instead of a "Class const *" ("YAQEBV" vs "YAPEBV"). Is this expected behavior?It's consistent. D's const is transitive, and D doesn't allow you to specify const on the indirection of a reference type. So there is no problem on the C++ mangling side of things, but, arguably, there is one in D's sementic, that isn't new. Something like differentiating "const(C) i" and "const C i" may be a good idea.
Mar 26 2017
On Sunday, March 26, 2017 14:51:28 Namespace via Digitalmars-d wrote:On Sunday, 26 March 2017 at 14:30:00 UTC, deadalnix wrote:You don't. Once part of a type is const, everything inside it is const. So, if a pointer is const, everything it points to is const. You can have the outer part be mutable with the inner part be const, but not the other way around. D's const can do tail-const, but it can't do head-const. Now, while you can't use const to make the pointer const and what it points to mutable, you _can_ make the the pointer read-only while still having what it points to be fully mutable by putting it in a struct which restricts write-access to the pointer. I believe that that's essentially what std.experimental.typecons.Final is supposed to do. Personally, I don't think that the fact that you can't use const for head-const in D is really a loss, since it's almost never what you want. Tail-const is _way_ more useful. But it is true that by making D's const fully transitive, there are variations of constness that C++ can do that D can't. immutable pretty much forces that though, and it does simplify the language. - Jonathan M DavisOn Sunday, 26 March 2017 at 10:43:11 UTC, Benjamin Thaut wrote:After reading your post, I wonder: How could I translate the following C++ code to D? ---- int a = 2; int* const p = &a; ----As you see from the above example D mangles the getClassConst as a "Class const * const" instead of a "Class const *" ("YAQEBV" vs "YAPEBV"). Is this expected behavior?It's consistent. D's const is transitive, and D doesn't allow you to specify const on the indirection of a reference type. So there is no problem on the C++ mangling side of things, but, arguably, there is one in D's sementic, that isn't new. Something like differentiating "const(C) i" and "const C i" may be a good idea.
Mar 26 2017
On Sunday, 26 March 2017 at 15:29:02 UTC, Jonathan M Davis wrote:Personally, I don't think that the fact that you can't use const for head-const in D is really a loss, since it's almost never what you want. Tail-const is _way_ more useful. But it is true that by making D's const fully transitive, there are variations of constness that C++ can do that D can't. immutable pretty much forces that though, and it does simplify the language.There are quite a few things wrong with const, it's so bad phobos isn't even const-correct when it should be. In cmp() for example, if you pass a lambda that takes the parameters by reference. You will be modifying temporary values that cmp() created on the stack. These should be const, but then what if it is a pointer? It is a different situation and you don't really want const cause you are going to be modifying the correct struct (the one pointed to). It is just easier to not use const in D cause it makes your code more difficult to actually use. That's exactly what Phobos does, it ignores const for the most part because it is easier not to use it.
Mar 26 2017
On Sunday, March 26, 2017 18:31:52 Jerry via Digitalmars-d wrote:On Sunday, 26 March 2017 at 15:29:02 UTC, Jonathan M Davis wrote:There are significant pros and cons when comparing C++ and D's const, but they usually relate to the ability to get around const in C++ and the lack of ability to do so in D. The ability to create a const pointer to a mutable element is occasionally something that someone wants to do, but in my experience, it's pretty useless. I'm not sure that I've ever used it in C++ (and I've programmed professinally primarily in C++), and when I was learning Java and found out that that's what Java's final did, I decided that all it was good for was constants of built-in types, and I think that that's mostly what I've seen other folks do with it. Having a pointer/reference that can't change while what it points to can just isn't very useful. It's having a mutable pointer to const that's useful. Now, as for const in D in general and how it compares to C++, that's a rather difficult question and highly debatable (and it's been debated here on many occasions). C++'s const is little more than documentation. It prevents accidental mutation, but there are so many ways around it that it's borderline meaningless. It only works as well as it does, because it's a convention that programmers _usually_ hold to. But it gurantees almost nothing. For instance, it's perfectly possible to have a class where all of its members are const but where all of them mutate the state of the object. The fact that that doesn't normally happen is simply because fortunately, programmers normally choose to behave themselves with mutable and casting away const. But they don't have to, and the compiler doesn't enforce it. D's const, on the other hand, has strong guarantees about something that's const never being mutated unless something elsewhere in the code has access to a mutable reference and changes the data that way. The const reference is never able to change the data without violating the type system. So, D's const actually means something. It provides real guarantees. But the reality of the matter is that that's so restrictive that pretty quickly you simply can't use const. There are too many idioms that require backdoors to const - mutexes, memory management, lazy initializaiton, etc. So, the end result is that in C++, you don't have much in the way of guarantees, but you're able to use what you do have all over the place. Accidental mutation is prevented and programmer intention is conveyed, but not much of anything is really guaranteed. Whereas with D, you have the strong guarantees, and you can use const in certain circumstances, but you're quickly forced to use it in only very restricted circumstances - especially if user-defined types or templates are involved. Too much simply doesn't work with true const. What most code really needs is logical const, and the compiler can't guarantee that. As to whether C++ or D did a better job with const, I really don't know. I find C++'s const to be pretty terrible from the standpoint of what it really protects, and I only recall one time in my entire programming career that it's actually caught a bug for me, but it's still nice to be able to indicate that a function doesn't mutate its arguments, even if it's not actually guaranteed, since it's usually true. The fact that D's const provides the stronger guarantees is fantastic, but it's also so restrictive that it borders on useless. So, ultimately, I'm not very happy with either solution, and I don't know what the best one would be. Arguably, immutable is what's truly useful - though obviously, code has to be written with it in mind, because a lot of code won't work with it without that - but for it to do its job, D's const pretty much has to be the way it is. Even if we wanted C++'s const in D, we couldn't have it unless it didn't interoperate with immutable. And as for the C++ concept of "const-correctness", I think that the end result of all of this is that it really doesn't apply to D. When code is const-correct, that essentially means that it will compile with const and that it's theoretically, "logically" const - _not_ that it's actually const. It's about convention and conveying the intention of the programmer, not actually guaranteeing anything. And D's const is all about guarantees. For better or worse, I think anyone thinking about const-correctness with D code is almost certainly thinking about const the wrong way in D. And yes, the end result of all of this is that templated code can almost never use const. So, a _lot_ of Phobos doesn't use it. And on some level, that sucks, but I'm not sure that we'd really be any better off with C++'s const either. There are pros and cons both ways. - Jonathan M DavisPersonally, I don't think that the fact that you can't use const for head-const in D is really a loss, since it's almost never what you want. Tail-const is _way_ more useful. But it is true that by making D's const fully transitive, there are variations of constness that C++ can do that D can't. immutable pretty much forces that though, and it does simplify the language.There are quite a few things wrong with const, it's so bad phobos isn't even const-correct when it should be. In cmp() for example, if you pass a lambda that takes the parameters by reference. You will be modifying temporary values that cmp() created on the stack. These should be const, but then what if it is a pointer? It is a different situation and you don't really want const cause you are going to be modifying the correct struct (the one pointed to). It is just easier to not use const in D cause it makes your code more difficult to actually use. That's exactly what Phobos does, it ignores const for the most part because it is easier not to use it.
Mar 26 2017
On Sunday, 26 March 2017 at 14:30:00 UTC, deadalnix wrote:It's consistent. D's const is transitive, and D doesn't allow you to specify const on the indirection of a reference type. So there is no problem on the C++ mangling side of things, but, arguably, there is one in D's sementic, that isn't new.I disagree. When binding C++ code to D I don't care about D's const rules. I care about the C++ const rules. There are thousands of C++ libraries out there that can't be bound to D because they use const Class* instead of const Class* const. So in my eyes there is definitly something wrong with the C++ mangling of D.
Mar 26 2017
On Sunday, 26 March 2017 at 17:41:57 UTC, Benjamin Thaut wrote:On Sunday, 26 March 2017 at 14:30:00 UTC, deadalnix wrote:It is clear that you won't be able to express 100% of C++ in D, that would require to important all the weird parts of C++ into D, but if we are doing so, why use D in the first place ? Note that using const Class* in C++ is essentially useless. The class remains mutable and the reference is local the the callee anyway, so it doesn't change anything for the caller. Such a pattern is most likely indicative of a bug on the C++ side, or at least of code that do not do what the author intend to.It's consistent. D's const is transitive, and D doesn't allow you to specify const on the indirection of a reference type. So there is no problem on the C++ mangling side of things, but, arguably, there is one in D's sementic, that isn't new.I disagree. When binding C++ code to D I don't care about D's const rules. I care about the C++ const rules. There are thousands of C++ libraries out there that can't be bound to D because they use const Class* instead of const Class* const. So in my eyes there is definitly something wrong with the C++ mangling of D.
Mar 26 2017
On Sunday, 26 March 2017 at 22:29:56 UTC, deadalnix wrote:It is clear that you won't be able to express 100% of C++ in D, that would require to important all the weird parts of C++ into D, but if we are doing so, why use D in the first place ? Note that using const Class* in C++ is essentially useless. The class remains mutable and the reference is local the the callee anyway, so it doesn't change anything for the caller. Such a pattern is most likely indicative of a bug on the C++ side, or at least of code that do not do what the author intend to.For `const Class*` the Class is not mutable. It is the case of `Class* const` that Class is mutable. I see a lot of people in D say similar things about it. Saying it is a bug, saying it's a good thing that a const pointer with mutable type isn't in D. Yet they always tend to be the people that have never actually used C++. As is indicative of not even knowing the correct syntax to use in C++. A common matter in C++ is to use templates, you may have seen it, it's a really common pattern, `const T&`. The magic that makes this work is that you read it like this: `T const &`. They both mean the samething but I find makes more sense, conceptually to read it like that. Now substitute a type for T, `int* const &`. You see here that int is mutable for this template. You can see my other post about cmp(), and how Phobos avoids usages of const as it just makes writing generic code difficult.
Mar 26 2017
On Sunday, 26 March 2017 at 22:56:59 UTC, Jerry wrote:On Sunday, 26 March 2017 at 22:29:56 UTC, deadalnix wrote:You are correct. See my first post for an explanation of this specific case.It is clear that you won't be able to express 100% of C++ in D, that would require to important all the weird parts of C++ into D, but if we are doing so, why use D in the first place ? Note that using const Class* in C++ is essentially useless. The class remains mutable and the reference is local the the callee anyway, so it doesn't change anything for the caller. Such a pattern is most likely indicative of a bug on the C++ side, or at least of code that do not do what the author intend to.For `const Class*` the Class is not mutable. It is the case of `Class* const` that Class is mutable.
Mar 27 2017
On 3/26/2017 3:29 PM, deadalnix wrote:Note that using const Class* in C++ is essentially useless. The class remains mutable and the reference is local the the callee anyway, so it doesn't change anything for the caller. Such a pattern is most likely indicative of a bug on the C++ side, or at least of code that do not do what the author intend to.Ironically, because C++ const is not transitive, most programmers use const in C++ as if it was transitive. This is most evident in templates where: const T is used.
Mar 27 2017
On Sunday, 26 March 2017 at 17:41:57 UTC, Benjamin Thaut wrote:There are thousands of C++ libraries out there that can't be bound to D because they use const Class* instead of const Class* const. So in my eyes there is definitly something wrong with the C++ mangling of D.I agree that C++-mangling a const D object reference as `const T *const` isn't helpful although it would be consistent with D semantics. As deadalnix pointed out, the const for the pointer itself only concerns the callee and not the caller. I sometimes use `void foo(const T *bla); ... void foo(const T *const bla) { ... }` if I find it useful to make clear that `bla` won't change in my foo() implementation, but I never use the second const in the function declaration in the header as it's just useless clutter for the caller. Having said that, you can only declare a C++ type as D class if it's exclusively passed and returned as pointer (at least in the parts you are going to interface with via D). This was true for the C++-based DMD front-end and would also be true for some types used in LLVM. But as soon as you want to interface with a C++ function taking an object as `[const] T&`, afaik you're f*cked and need to declare it as D struct. So I'm quite skeptical that I'll often be able to use D classes to represent C++ types.
Mar 27 2017
On 3/26/2017 3:43 AM, Benjamin Thaut wrote:Should I open a bug for this?It's not a bug, it was intended that way. The trouble is that D cannot express a <const pointer> to <mutable>. Whichever way it is mangled will gore someone's ox. D went with the simplest mangling solution, which is to mangle all C++ const pointers as "head const". The obvious solution is to implement "head const" in D, but that is a major change to the type system and the philosophy of D. I suggest a simpler way - declare the C++ side of the D interface in a way that matches the way D mangles it. It's always been true that in order to interface D with C++ you'll need to be a bit flexible on the C++ side.
Mar 27 2017
On Monday, 27 March 2017 at 20:09:35 UTC, Walter Bright wrote:Whichever way it is mangled will gore someone's ox. D went with the simplest mangling solution, which is to mangle all C++ const pointers as "head const". [...] I suggest a simpler way - declare the C++ side of the D interface in a way that matches the way D mangles it. It's always been true that in order to interface D with C++ you'll need to be a bit flexible on the C++ side.Unfortunately, it's almost always the other way around - D code trying to interop with one of the gazillions existing C++ libs, and nobody wants to maintain his own fork with D-compatible glue interfaces. How often did you use `const T *const` vs. `const T *` in your C++ headers? ;) I think this would be a tiny change for D, breaking almost no code and well worth the reduction in required 'flexibility on the C++ side'.
Mar 27 2017
On 3/27/2017 1:41 PM, kinke wrote:Unfortunately, it's almost always the other way around - D code trying to interop with one of the gazillions existing C++ libs, and nobody wants to maintain his own fork with D-compatible glue interfaces. How often did you use `const T *const` vs. `const T *` in your C++ headers? ;) I think this would be a tiny change for D, breaking almost no code and well worth the reduction in required 'flexibility on the C++ side'.It's made to work with: const T which is the norm with C++ templates.
Mar 27 2017
On Monday, 27 March 2017 at 22:04:55 UTC, Walter Bright wrote:On 3/27/2017 1:41 PM, kinke wrote:Okay, so how exactly do I bind D code to a C++ header-only-template library? I thought that in that case you need a full D translation anyway...Unfortunately, it's almost always the other way around - D code trying to interop with one of the gazillions existing C++ libs, and nobody wants to maintain his own fork with D-compatible glue interfaces. How often did you use `const T *const` vs. `const T *` in your C++ headers? ;) I think this would be a tiny change for D, breaking almost no code and well worth the reduction in required 'flexibility on the C++ side'.It's made to work with: const T which is the norm with C++ templates.
Mar 27 2017
On 3/27/2017 3:12 PM, kinke wrote:C++ templates are always header-only. I don't really understand your question.It's made to work with: const T which is the norm with C++ templates.Okay, so how exactly do I bind D code to a C++ header-only-template library? I thought that in that case you need a full D translation anyway...
Mar 27 2017
On Monday, 27 March 2017 at 22:24:26 UTC, Walter Bright wrote:On 3/27/2017 3:12 PM, kinke wrote:Yep, so there are no libs my D code can link to, so how am I supposed to use C++ templates from D (as you're using that as argument for the `const T *const` mangling)?C++ templates are always header-only. I don't really understand your question.It's made to work with: const T which is the norm with C++ templates.Okay, so how exactly do I bind D code to a C++ header-only-template library? I thought that in that case you need a full D translation anyway...
Mar 27 2017
On 3/27/2017 3:30 PM, kinke wrote:On Monday, 27 March 2017 at 22:24:26 UTC, Walter Bright wrote:There's still a miscommunication here, as header-only template libraries are not linked to.On 3/27/2017 3:12 PM, kinke wrote:Yep, so there are no libs my D code can link to, so how am I supposed to use C++ templates from D (as you're using that as argument for the `const T *const` mangling)?C++ templates are always header-only. I don't really understand your question.It's made to work with: const T which is the norm with C++ templates.Okay, so how exactly do I bind D code to a C++ header-only-template library? I thought that in that case you need a full D translation anyway...
Mar 27 2017
On 2017-03-28 00:30, kinke wrote:Yep, so there are no libs my D code can link to, so how am I supposed to use C++ templates from D (as you're using that as argument for the `const T *const` mangling)?As far as I understand, D can link with C++ templates if they're instantiated on the C++ side. It would link with the instantiated template not the actual template. -- /Jacob Carlborg
Mar 28 2017
On 3/28/2017 11:12 AM, Jacob Carlborg wrote:As far as I understand, D can link with C++ templates if they're instantiated on the C++ side. It would link with the instantiated template not the actual template.Recall that dmd itself connected to C++ templates when the front end was not full in D.
Mar 28 2017
On Monday, March 27, 2017 20:41:51 kinke via Digitalmars-d wrote:On Monday, 27 March 2017 at 20:09:35 UTC, Walter Bright wrote:Realistically, unless D fully supports C++ (which pretty much means that it has to become C++ on some level), you're almost always going to be stuck with some sort of glue layer between D code and C++ code. There's no reasonable way around that. We can work to improve the situation so that more C++ stuff just works when hooking up to D, but we'll never get all the way there, because that would mean dragging C++ into D, which we really don't want. There was talk at one point of trying to declare some sort of extern(C++) const that worked more like C++'s const, but even just that would be a huge mess and would further complicate the already overly complicated situation with const in D. And for that matter, even though D is highly compatible with C code, you still have to worry about maintaining all of the bindings. So, even then, you're still basically dealing with a glue layer to maintain, even if it's just there to tell D about the symbols in C land rather than adding any real code. Any time that D interacts with another language, _someone_ is going to have to maintain some sort of glue layer, even if it's a very thin layer, and to a great extent, I think that eliminating that layer is a pipe dream, though I do agree that improvements to make it thinner would certainly be nice (assuming that the cost isn't too high). Now, as for this particular case with const, I really don't know what should be done. What's currently done _is_ the most correct, but it's also something that really isn't what would be done normally in C++ - at least not outside of templated code. Pointers to const are _very_ prevalent, but const pointers to const really aren't. But I'd also be worried about what quirks and problems we'd end up with if we tried to mangle extern(C++)'s const with semantics that didn't match D's semantics, even if in most cases, it wouldn't matter. Also, in general, unless a C++ function was written to be called from D, I don't know how likely it is to work very well. It definitely _can_ work, but from what I've seen thus far, you tend to need to create C++ wrappers to interact with D code anyway, and if you do that, you just write the C++ functions with the correct constness, and it's no longer a problem. - Jonathan M DavisWhichever way it is mangled will gore someone's ox. D went with the simplest mangling solution, which is to mangle all C++ const pointers as "head const". [...] I suggest a simpler way - declare the C++ side of the D interface in a way that matches the way D mangles it. It's always been true that in order to interface D with C++ you'll need to be a bit flexible on the C++ side.Unfortunately, it's almost always the other way around - D code trying to interop with one of the gazillions existing C++ libs, and nobody wants to maintain his own fork with D-compatible glue interfaces. How often did you use `const T *const` vs. `const T *` in your C++ headers? ;) I think this would be a tiny change for D, breaking almost no code and well worth the reduction in required 'flexibility on the C++ side'.
Mar 27 2017
On Tuesday, 28 March 2017 at 02:14:25 UTC, Jonathan M Davis wrote:Realistically, unless D fully supports C++ (which pretty much means that it has to become C++ on some level), you're almost always going to be stuck with some sort of glue layer between D code and C++ code. There's no reasonable way around that. We can work to improve the situation so that more C++ stuff just works when hooking up to D, but we'll never get all the way there, because that would mean dragging C++ into D, which we really don't want.I know that. I'm just arguing for this tiny change in C++-mangling of D const object references as a remedy for this one particular issue out of many wrt. C++ interop. What I don't get is why it's considered important to have a matching C++ mangling for templates across D and C++ - what for? I only care about mangling wrt. interop if I wanna link to some foreign code, and with templates I can't, so I see absolutely no problem with a D template `extern (C++) void foo()(const(Object) arg)` being mangled slightly differently (arg as `const Object*`) than a C++ template `template <typename T> void foo(const T arg)` with `T = const Object*` (arg as `const Object* const`). Don't get me wrong, I don't advocate C++-mangling a D `const(S*)` for some struct S as `const S*` at all - we're talking specifically about D class references here, which don't have a direct C++ analogon, so choosing to C++-mangle them in a special way sounds absolutely feasible to me.
Mar 28 2017
On Tuesday, 28 March 2017 at 08:30:43 UTC, kinke wrote:What I don't get is why it's considered important to have a matching C++ mangling for templates across D and C++ - what for? I only care about mangling wrt.If you still think this is a mangling problem, please reread my first response in this thread.
Mar 28 2017
On Tuesday, 28 March 2017 at 12:55:02 UTC, deadalnix wrote:On Tuesday, 28 March 2017 at 08:30:43 UTC, kinke wrote:You don't seem to get my point, I don't know why it's apparently that hard. I don't want to be able to express both `const T* const` AND `const T*` in C++, I only want D's const(Object) mangling to express solely the former instead of the latter, as there's no use for the double-const, except maybe for templates as Walter pointed out, but there's no template interop between D and C++ anyway. I absolutely don't care that it's inconsistent to what a D const(Object) reference actually is (both pointer and class const) when passing such a thing BY VALUE to C++. As I said, there's no C++ analogon for D object references, so why not have it be a special case in the C++ mangler...What I don't get is why it's considered important to have a matching C++ mangling for templates across D and C++ - what for? I only care about mangling wrt.If you still think this is a mangling problem, please reread my first response in this thread.
Mar 28 2017
On Tuesday, 28 March 2017 at 13:18:57 UTC, kinke wrote:You don't seem to get my point, I don't know why it's apparently that hard.It's hard because you assume I did not understood you point and you keep repeating the same thing. I understand you point and showed you why it isn't a mangling problem at all, and gave you direction you may want to dig in to make a proposal that may actually get traction. But you can chose to entrench yourself in a position were nobody understands your genius. You won't get any result, but depending on your personality, it may make you feel good, which is already something.
Mar 28 2017
On Tuesday, 28 March 2017 at 14:11:16 UTC, deadalnix wrote:I understand you point and showed you why it isn't a mangling problem at all, and gave you direction you may want to dig in to make a proposal that mayactually get traction. If you really did get my point, it should be clear that I don't see a necessity for differentiating between `const T` and `const(T)` on the D side in general, transitive const hasn't been an issue for my D/C++ interop use cases yet, but the const(Object) issue the OP arises would definitely be a show stopper at some point and, unlike a more general solution, can be trivially remedied.
Mar 28 2017
On Tue, Mar 28, 2017 at 11:21 PM kinke via Digitalmars-d < digitalmars-d puremagic.com> wrote:On Tuesday, 28 March 2017 at 12:55:02 UTC, deadalnix wrote:I've lost sleep on this point for many years. I keep changing my mind between purity and what's actually useful, but I've settled on what you say here. It is my opinion from a decade of experience that D should mangle const(Class) as `const Class *`. It is what you want 99% of the time. There's some precedent for this too; C++ actually strips the head const off of the types when mangling function arguments. For instance: void t(const int *); void t(const int * const); Both functions mangle to `void t(const int *)` (and this is an invalid overload). The pointer const is not present in the mangling here. We follow this rule when mangling const class arguments to functions. In this case, we strip the pointer const from the mangling (as does C++). The case where it can go either way is with templates: void foo<const Class * const>(); void foo<const Class *>(); These are valid overloads... and D can only express the former instantiation, which basically never occurs in C++. I accept that they are functionally different things, and 'correct-ness' says that we should indeed mangle the former one, but that's just not useful. I think even in the template case, we should mangle const(Class) to `const Class *`, and not `const Class * const`. It is possible to conjure an exploit where C++ may modify a const D variable across the binding, but that's extremely contrived, and the capabilities our current mangling limits us from is an endless pain in the arse.On Tuesday, 28 March 2017 at 08:30:43 UTC, kinke wrote:You don't seem to get my point, I don't know why it's apparently that hard. I don't want to be able to express both `const T* const` AND `const T*` in C++, I only want D's const(Object) mangling to express solely the former instead of the latter, as there's no use for the double-const, except maybe for templates as Walter pointed out, but there's no template interop between D and C++ anyway. I absolutely don't care that it's inconsistent to what a D const(Object) reference actually is (both pointer and class const) when passing such a thing BY VALUE to C++. As I said, there's no C++ analogon for D object references, so why not have it be a special case in the C++ mangler...What I don't get is why it's considered important to have a matching C++ mangling for templates across D and C++ - what for? I only care about mangling wrt.If you still think this is a mangling problem, please reread my first response in this thread.
Aug 25 2020
On Monday, 27 March 2017 at 20:41:51 UTC, kinke wrote:On Monday, 27 March 2017 at 20:09:35 UTC, Walter Bright wrote:I just ran into this problem too. Is there some way around this with pragma(mangle)? Forking the 3rd-party library would be my last resort. If there's a way that I can write the declaration in D I would prefer to do that.Whichever way it is mangled will gore someone's ox. D went with the simplest mangling solution, which is to mangle all C++ const pointers as "head const". [...] I suggest a simpler way - declare the C++ side of the D interface in a way that matches the way D mangles it. It's always been true that in order to interface D with C++ you'll need to be a bit flexible on the C++ side.Unfortunately, it's almost always the other way around - D code trying to interop with one of the gazillions existing C++ libs, and nobody wants to maintain his own fork with D-compatible glue interfaces. How often did you use `const T *const` vs. `const T *` in your C++ headers? ;) I think this would be a tiny change for D, breaking almost no code and well worth the reduction in required 'flexibility on the C++ side'.
Aug 25 2020
On Wednesday, 26 August 2020 at 00:41:18 UTC, Nathan S. wrote:I just ran into this problem too. Is there some way around this with pragma(mangle)?For anyone else wondering: it turns out yes, pragma(mangle) works even with virtual functions. I didn't find a convenient way of generating the mangling other than inspecting the object file and copying the mangled name by hand, but that works fine for a small number of functions.
Aug 26 2020
On 3/26/2017 3:43 AM, Benjamin Thaut wrote:Should I open a bug for this?https://issues.dlang.org/show_bug.cgi?id=21200
Aug 26 2020