Re: Specifying C++ symbols in C++ namespaces
On Sat, 05 Apr 2014 13:47:32 -0700, Walter Bright newshou...@digitalmars.com wrote: On 4/2/2014 3:07 PM, Walter Bright wrote: One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it: extern (C++, namespace = A.B) { void foo(); void bar(); } extern (C++, namespace = C) void foo(); bar(); // works A.B.bar(); // works foo(); // error: ambiguous C.foo(); // works alias C.foo foo; foo(); // works, calling C.foo() I really think the namespace semantics should be attached to the extern(C++) rather than be a separate pragma. Having the namespace= thing means that namespace isn't a keyword, and provides a general mechanism where we can add language specific information as necessary. This seems like a reasonable way to interop with C++ namespace in a D way. I also think that it is something that we should do ASAP. I know that for Aurora, I will not be able to add complete DirectX support until the C++ namespace interop problem is solved. Specifically because the highly optimized DirectXMath functions are inside a namespace. I do not consider pre-mangling a solution, it's a hack for something that is quite common in C++, and it's fragile. -- Adam Wilson GitHub/IRC: LightBender Aurora Project Coordinator
Re: Specifying C++ symbols in C++ namespaces
On Monday, 7 April 2014 at 01:35:37 UTC, Michel Fortin wrote: Modules are already in use on OS X for some system frameworks. It can result in slightly improved compile times. It has been enabled by default for new Xcode projects for some time. Thanks for sharing, I wasn't aware of that. That means that clang will make this a priority. But I guess clang is a long way from not having end users write their own header files still.
Re: Specifying C++ symbols in C++ namespaces
On Monday, 7 April 2014 at 08:06:11 UTC, Ola Fosheim Grøstad wrote: On Monday, 7 April 2014 at 01:35:37 UTC, Michel Fortin wrote: Modules are already in use on OS X for some system frameworks. It can result in slightly improved compile times. It has been enabled by default for new Xcode projects for some time. Thanks for sharing, I wasn't aware of that. That means that clang will make this a priority. But I guess clang is a long way from not having end users write their own header files still. clang developers are the ones driving the ISO C++ Modules working group, so whatever clang does, it will eventually be the standard. -- Paulo
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 20:47:29 UTC, Walter Bright wrote: On 4/2/2014 3:07 PM, Walter Bright wrote: One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it: extern (C++, namespace = A.B) { void foo(); void bar(); } extern (C++, namespace = C) void foo(); bar(); // works A.B.bar(); // works foo(); // error: ambiguous C.foo(); // works alias C.foo foo; foo(); // works, calling C.foo() I really think the namespace semantics should be attached to the extern(C++) rather than be a separate pragma. Having the namespace= thing means that namespace isn't a keyword, and provides a general mechanism where we can add language specific information as necessary. I actually like this idea the most. It is clean, and easy to understand.
Re: Specifying C++ symbols in C++ namespaces
On 4/6/2014 2:56 AM, Marc Schütz schue...@gmx.net wrote: And wouldn't it clash with D's std package? Yes. But D has numerous methods of disambiguation.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 23:26:30 UTC, Walter Bright wrote: I feel that C++ messed up namespace design because: 1. namespaces are not closed 2. they have no relationship with modules Namespaces are not as powerful as they could have been, but being able to add symbols to an external scope (like classes) is very useful if done right (e.g. cross-cutting enhancements, adding members to external classes like saveyourself, printyourself). which has wound up forcing the addition of Yet Another Design when imports and modules are added to C++. Unfortunately that seems to be years into the future? Although clang has begun implementing something: http://clang.llvm.org/docs/Modules.html I've got at feeling that if clang gets something working it will become a de-facto standard due to demand.
Re: Specifying C++ symbols in C++ namespaces
On 4/6/2014 12:39 PM, Ola Fosheim Grøstad ola.fosheim.grostad+dl...@gmail.com wrote: On Saturday, 5 April 2014 at 23:26:30 UTC, Walter Bright wrote: I feel that C++ messed up namespace design because: 1. namespaces are not closed 2. they have no relationship with modules Namespaces are not as powerful as they could have been, but being able to add symbols to an external scope (like classes) is very useful if done right (e.g. cross-cutting enhancements, adding members to external classes like saveyourself, printyourself). It's seriously wrong to allow such. It makes a larger code base nearly impossible to reliably reason about, leading one to rely on conventions like don't add stuff to namespaces. D has closed scopes, and members can be added to external classes just fine, using CTFE.
Re: Specifying C++ symbols in C++ namespaces
On Sunday, 6 April 2014 at 20:17:09 UTC, Walter Bright wrote: It's seriously wrong to allow such. It makes a larger code base nearly impossible to reliably reason about, leading one to rely on conventions like don't add stuff to namespaces. Depends on how it is done. For BETA, there was a seperate fragment system that allowed AST specified extension points. This system was used for both extensions and for encapsulation/API definition. You basically defined slots in the syntax three where code could be injected (following the grammar of the slot) and what should be hidden etc. It was simplistic elegance IMO: http://www.cs.au.dk/~beta/Manuals/latest/beta/fragment.html The weakness was that they didn't allow for dynamic dispatch (required static resolution), but that was an implementation issue, I think.
Re: Specifying C++ symbols in C++ namespaces
Btw, cross-cutting programming is indeed meant to cater for programming in the large: http://en.wikipedia.org/wiki/Aspect-oriented_programming
Re: Specifying C++ symbols in C++ namespaces
On Sunday, 6 April 2014 at 20:17:09 UTC, Walter Bright wrote: D has closed scopes, and members can be added to external classes just fine, using CTFE. You mean UFCS? As in, for example, front for arrays? It doesn't work as well as advertised though. The issue is that the added members are only visible if the *called* code knows to import the *caller* code. This breaks as soon as you leave your own internal ecosystem. // import a; struct S //Some object { } //Extend to make it a range. bool empty(S); int front(S); void popFront(S); //Try it. void main() { S s; foreach(e; s) //Error: invalid foreach aggregate s writeln(s); s.array(); //Error: template std.range.take cannot... a.foo(s); //Error: no property 'popFront' for type 'S' } // module a; void foo(T)(T t) { t.popFront(); } // Well that horribly fails. Because when calling a template, you are only importing the passed argument, but not his ecosystem with it. The only way in D to really extend an existing object, is to wrap it into a new object. And even then, the wrapping is limited, because you can't orthogonally wrap (eg the wrapping linearly stacks, whereas UCFS *could* add two completely independent functionalities). Not to mention issues with code bloat... C++'s namespaces have their flaws, but they *are* scalable in a way D's modules aren't, thanks to Koenig Lookup.
Re: Specifying C++ symbols in C++ namespaces
On 4/6/2014 2:00 PM, monarch_dodra wrote: On Sunday, 6 April 2014 at 20:17:09 UTC, Walter Bright wrote: D has closed scopes, and members can be added to external classes just fine, using CTFE. You mean UFCS? Yes, my mistake. As in, for example, front for arrays? It doesn't work as well as advertised though. The issue is that the added members are only visible if the *called* code knows to import the *caller* code. That's a feature of a modular system, not a bug. D does not have a global name space, on purpose. This breaks as soon as you leave your own internal ecosystem. // import a; struct S //Some object { } //Extend to make it a range. bool empty(S); int front(S); void popFront(S); //Try it. void main() { S s; foreach(e; s) //Error: invalid foreach aggregate s writeln(s); s.array(); //Error: template std.range.take cannot... a.foo(s); //Error: no property 'popFront' for type 'S' } // module a; void foo(T)(T t) { t.popFront(); } // Well that horribly fails. That's based on a misunderstanding of how scoped lookup works in D, and how to use it properly. In the particular instance above, there is simply no reason to not put front() as a member of S, since they are in the same module. Because when calling a template, you are only importing the passed argument, but not his ecosystem with it. The only way in D to really extend an existing object, is to wrap it into a new object. And even then, the wrapping is limited, because you can't orthogonally wrap (eg the wrapping linearly stacks, whereas UCFS *could* add two completely independent functionalities). Not to mention issues with code bloat... You're right in that if you try to do things the C++ way in D, things won't work out so well. D can do all these things, but they are done in a different way - a way that is much more robust. The fault in the C++ method of extending namespaces is that two independently developed modules had better not extend the same namespace with the same names. You will not necessarily get a compiler error from violating this - code may just wind up calling the wrong overload. I.e. it does not scale. C++'s namespaces have their flaws, but they *are* scalable in a way D's modules aren't, thanks to Koenig Lookup. I've never seen anyone defend Koenig lookup as anything but a hack before :-)
Re: Specifying C++ symbols in C++ namespaces
On 2014-04-05 22:42, Walter Bright wrote: 2. C++ namespaces are very low hanging fruit, with a significant payoff. It's worthwhile. I think it's very low hanging fruit to add support for basic C++ namespaces. Support for basically just set the mangled name in a somewhat nice way, a pragma for example. If we're talking about adding something more advanced like :: or extern (C++) template which my affect the current name look up rules then I don't think that's so low hanging fruit anymore. -- /Jacob Carlborg
Re: Specifying C++ symbols in C++ namespaces
I think it's very low hanging fruit to add support for basic C++ namespaces. Support for basically just set the mangled name in a somewhat nice way, a pragma for example. I think it is more important to think in term of strategic positions than whether it takes 1 or 2 weeks to implement a feature. Assumption: It is desirable to make the eco system more attractive for commercial projects. Key requirements: - Long term stability of the dev environment. - Access to mature libraries with significant backing (basically C/C++ libraries). - Easy integration with existing technology and systems (basically C/C++). - No lock-in (basically C/C++ interop). - Predictable dev environment that enables precise cost estimates. - Lowering costs/faster development than the alternatives (more convinient than C/C++) If you cannot assume that you can utilize a C++ library from D or if you have to assume that using a C++ library might incur a significant interfacing overhead (in terms of programmer's time) then D looks like a more risky proposition. The key difference between a commercial project and a hobby project is that the hobby project can fully adapt the requirements to the dev environment. A hobbyist game project can settle for a less capable physics engine or create a custom one, for fun. A commercial project will view that as costs that cut into profit margins and a potential source of failure in the market. That's a good reason to go with C++ instead of D. From a strategic point of view it is important to fully support those features you claim to support. If you can claim that interfacing with C++, except for templates, is easy, then you communicate that it is relatively easy to assess project costs. If you only claim that it is possible to interface with some of C++, but that it is kind of difficult under certain vaguely specified circumstances then I think you should wait until you have a better solution. What you absolutely don't want is to trick people into thinking that interfacing with C++ is easy, if it isn't, and have them discover that they are better off dumping D and doing it all over in C++.
Re: Specifying C++ symbols in C++ namespaces
On Sunday, 6 April 2014 at 02:33:38 UTC, Walter Bright wrote: On 4/5/2014 6:26 PM, Michel Fortin wrote: What if you also have a C++ foo at global scope? It'll work exactly the same as import does. module cpptest; extern (C++) void foo(); extern (C++, namespace = A) void foo(); foo(); // ambiguous A.foo(); // works .foo(); // works? Yes. cpptest.foo(); // works? Yes. Does these two last lines make sense? Just as much sense as: module bar; void foo(); .foo(); // works bar.foo(); // works Namespace lookup rules would be exactly the same as for imports and mixin templates. My main reservation against the new suggestion is that one would be forced to open a new nested namespace even when it's detrimental, because in some cases the namespace structure is already reflected in the filesystem(just like for D:s module system). I can't assess how widespread this is globally, but at least some high-quality projects already have guidelines to use file/namespace mappings. A random example from boost: boost::asio::ip::multicast boost/asio/ip/multicast.hpp One can of course workaround this issue with an extra alias for every imported symbol, or use compile-time reflection to auto-generate all alias statements... (or heaven forbid, put entire boost in one file ;)) I assume the namespace = xxx syntax is some sort of named parameter, would it be possible to add another similar param, which only changes mangling and doesn't actually create a new scope?
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 21:43:03 UTC, Walter Bright wrote: On 4/5/2014 2:31 PM, Tove wrote: How could this common pattern look? std::string boost::fun(std::string arg) alias cpp= extern (C++, namespace = std); alias boost = extern (C++, namespace = boost); cpp.string boost.fun(cpp.string arg) ? extern (C++, namespace = std) { struct string { ... } } extern (C++, namespace = boost) { void fun(std.string arg); } What would std be here from D's point of view? A module? Or a new kind of symbol? And wouldn't it clash with D's std package?
Re: Specifying C++ symbols in C++ namespaces
On 2014-04-06 19:39:31 +, Ola Fosheim Grøstad ola.fosheim.grostad+dl...@gmail.com said: Unfortunately that seems to be years into the future? Although clang has begun implementing something: http://clang.llvm.org/docs/Modules.html I've got at feeling that if clang gets something working it will become a de-facto standard due to demand. Modules are already in use on OS X for some system frameworks. It can result in slightly improved compile times. It has been enabled by default for new Xcode projects for some time. With modules enabled, clang interpret #includes as module imports for system frameworks having a module map. It's so transparent you probably won't notice anything has changed. The only thing that really changes with modules is you don't have access to symbols you don't have imported yourself. D already works like that. I think D can ignore those modules, just like it ignores header files. -- Michel Fortin michel.for...@michelf.ca http://michelf.ca
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 22:17:45 UTC, Dicebot wrote: #2 should not compile. D currently does not have any notion of namespaces other than modules / aggregates and I am against introducing those just for the sake of interfacing with C++. If you want to interface with C++ you should do it well or not at all. In C++ namespace names reside in their own namespace which means that you get short names like std, qt etc. Which in turn means you have to rename those to CPPstd, CPPqt etc in D in order to disambiguate the symbols. Having a dedicated namespace operator would be a lot more convenient.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 08:42:27 UTC, Ola Fosheim Grøstad wrote: On Friday, 4 April 2014 at 22:17:45 UTC, Dicebot wrote: #2 should not compile. D currently does not have any notion of namespaces other than modules / aggregates and I am against introducing those just for the sake of interfacing with C++. If you want to interface with C++ you should do it well or not at all. In C++ namespace names reside in their own namespace which means that you get short names like std, qt etc. Which in turn means you have to rename those to CPPstd, CPPqt etc in D in order to disambiguate the symbols. Having a dedicated namespace operator would be a lot more convenient. D has own tools to disambugate symbols. Introducing new ones is equivalent to admitting D module system does not work by design.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 12:07:36 UTC, Dicebot wrote: D has own tools to disambugate symbols. Introducing new ones is equivalent to admitting D module system does not work by design. I think it is primarily a notation issue. Should the notation help you discern what is C++ and what is D, or do you have to memorize symbols? How much extra notational work is it acceptable to impose on the programmer? There are advantages and disadvantages to both approaches. Pro explicit c++ namespaces: - Easy to discern what is C++ and what is D. - Less chance of future irreconcilable design conflicts when either C++ or D changes (e.g. C++18 and beyond) - Having a philosophy of native foreign functions rather than masquerading as D constructs makes it easier to integrate with other languages beyond c/c++ at a later stage. Con: - More syntax to understand for newbies - Requires a little bit more refactoring when moving C++ code to D.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 12:30:28 UTC, Ola Fosheim Grøstad wrote: Should the notation help you discern what is C++ and what is D, or do you have to memorize symbols? How much extra notational work is it acceptable to impose on the programmer? It shouldn't. The fact how entity is exposed via some external binary interface should not have any notable impact on D side of things (unless you dwell into ABI realm). This is exactly what extern is for - matching symbols from domain of D terms to some external alien domain.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 12:58:54 UTC, Dicebot wrote: It shouldn't. The fact how entity is exposed via some external binary interface should not have any notable impact on D side of things (unless you dwell into ABI realm). This is a design philosophical issue, you can make it normative if you want, but only if it is consistent with the overall design philosophy. Working on making that philosophy explicit is important, D2 is showing some signs of having gone through a lot of evolutionary design and IMHO signs of a need for notational redesign. Meaning: recreate the syntax to fit the desired semantics that the language has obtained over time (as in designing it, not evolving). Not distinguishing between C++/D does however have consequences: if foreign constructs have the same appearance as the language constructs then you should also make sure that all the semantics are the same. E.g. C++ exceptions, calls to C++ new etc have to be fully harmonized with D equivalents.
Re: Specifying C++ symbols in C++ namespaces
On 04/03/2014 09:55 PM, Andrei Alexandrescu wrote: ... Anyhow de gustibus. There's good and bad taste.
Re: Specifying C++ symbols in C++ namespaces
Not that I ever do this, but I think you need to deal with this C++ construct: namespace exposed_ns { using namespace internal_ns_2134zxdssdffrandomblablah; using namespace internal_ns_2634zasdsfsdrandomblablah; using namespace internal_ns_2993adsfadsfrandomblablah; } To do this in D you would have to be able to set up a search sequence as an alias somehow.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 13:11:27 UTC, Ola Fosheim Grøstad wrote: On Saturday, 5 April 2014 at 12:58:54 UTC, Dicebot wrote: It shouldn't. The fact how entity is exposed via some external binary interface should not have any notable impact on D side of things (unless you dwell into ABI realm). This is a design philosophical issue, you can make it normative if you want, but only if it is consistent with the overall design philosophy. This is very practical thing. By introducing special constructs to support some foreign language you open the can of worms. Where does one stop? Should we also expect adding some new idioms for better JNI support? Or Python? I can't see any reason why C++ has to be any special and you can't nicely support them all. We don't even truly do this for C and this the only real ABI standard.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 15:24:32 UTC, Dicebot wrote: This is very practical thing. By introducing special constructs to support some foreign language you open the can of worms. Yep, but I believe C++ is increasingly going to replace C as a language for writing basic libraries and engines in the next few decades. Which isn't great for interop, but a trend still.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 15:24:32 UTC, Dicebot wrote: This is very practical thing. By introducing special constructs to support some foreign language you open the can of worms. Where does one stop? Should we also expect adding some new idioms for better JNI support? Or Python? I can't see any reason why C++ has to be any special and you can't nicely support them all. We don't even truly do this for C and this the only real ABI standard. Another way to put this is that D is its own language, not a C++ extension. IMO, an FFI should make interoperability possible via ABI matching, but it should not compromise the language (by making its scoping rules more complicated, introducing redundant constructs, or introducing a new token (::) that could be used for another feature).
Re: Specifying C++ symbols in C++ namespaces
On 4/5/2014 8:24 AM, Dicebot wrote: This is very practical thing. By introducing special constructs to support some foreign language you open the can of worms. Where does one stop? Should we also expect adding some new idioms for better JNI support? Or Python? I can't see any reason why C++ has to be any special and you can't nicely support them all. We don't even truly do this for C and this the only real ABI standard. A very good question. Some points to consider: 1. D is supposed to be a practical language, and be designed to get s**t done. 2. D has long recognized that C++ exists and tries to be accommodating - with extern(C++) and C++ compatible COM classes. extern(C++) already does more than just adjust the name mangling. 3. There's significant demand for supporting C++ namespaces among people trying to migrate to D. There's more than just the people who post here. Currently, this is a barrier to adoption of D, and an unnecessary one. 4. I know I very much appreciate products that don't try and pretend they are the shiznit and nothing else exists. For example, Thunderbird Mail was able to import my old Outlook Express database perfectly, enabling me to completely abandon OE. 5. There's also work underway to better integrate with ObjectiveC. In the light of that: 1. We cannot nicely support them all. But we don't have to. We can support the low hanging fruit. 2. C++ namespaces are very low hanging fruit, with a significant payoff. It's worthwhile. 3. C++ is special because a) we can support limited interoperability without much effort and b) a lot of people come to D from C++ and want to interoperate.
Re: Specifying C++ symbols in C++ namespaces
On 4/2/2014 3:07 PM, Walter Bright wrote: One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it: extern (C++, namespace = A.B) { void foo(); void bar(); } extern (C++, namespace = C) void foo(); bar(); // works A.B.bar(); // works foo(); // error: ambiguous C.foo(); // works alias C.foo foo; foo(); // works, calling C.foo() I really think the namespace semantics should be attached to the extern(C++) rather than be a separate pragma. Having the namespace= thing means that namespace isn't a keyword, and provides a general mechanism where we can add language specific information as necessary.
Re: Specifying C++ symbols in C++ namespaces
On Saturday, 5 April 2014 at 20:47:29 UTC, Walter Bright wrote: On 4/2/2014 3:07 PM, Walter Bright wrote: One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it: extern (C++, namespace = A.B) { void foo(); void bar(); } extern (C++, namespace = C) void foo(); bar(); // works A.B.bar(); // works foo(); // error: ambiguous C.foo(); // works alias C.foo foo; foo(); // works, calling C.foo() I really think the namespace semantics should be attached to the extern(C++) rather than be a separate pragma. Having the namespace= thing means that namespace isn't a keyword, and provides a general mechanism where we can add language specific information as necessary. How could this common pattern look? std::string boost::fun(std::string arg) alias cpp= extern (C++, namespace = std); alias boost = extern (C++, namespace = boost); cpp.string boost.fun(cpp.string arg) ?
Re: Specifying C++ symbols in C++ namespaces
On 4/5/2014 2:31 PM, Tove wrote: How could this common pattern look? std::string boost::fun(std::string arg) alias cpp= extern (C++, namespace = std); alias boost = extern (C++, namespace = boost); cpp.string boost.fun(cpp.string arg) ? extern (C++, namespace = std) { struct string { ... } } extern (C++, namespace = boost) { void fun(std.string arg); }
Re: Specifying C++ symbols in C++ namespaces
On 2014-04-05 20:47:32 +, Walter Bright newshou...@digitalmars.com said: On 4/2/2014 3:07 PM, Walter Bright wrote: One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it: extern (C++, namespace = A.B) { void foo(); void bar(); } extern (C++, namespace = C) void foo(); bar(); // works A.B.bar(); // works foo(); // error: ambiguous C.foo(); // works alias C.foo foo; foo(); // works, calling C.foo() I really think the namespace semantics should be attached to the extern(C++) rather than be a separate pragma. Having the namespace= thing means that namespace isn't a keyword, and provides a general mechanism where we can add language specific information as necessary. I like this idea. But... should this potentially useful thing really be restricted to extern C++ things? I've seen at least one attempt to create a namespace using what D currently offers [1], and frankly something like the above would make much more sense than a class no one can instantiate. [1]: http://dlang.org/phobos/std_datetime.html#.Clock Here's a suggestion: @namespace A.B { // can create two levels at once, yeah! void foo(); void bar(); } @namespace C { void foo(); } Make those C++ declarations, it does not look too foreign anymore: extern (C++) @namespace A.B { void foo(); void bar(); } extern (C++) @namespace C { void foo(); } -- Michel Fortin michel.for...@michelf.ca http://michelf.ca
Re: Specifying C++ symbols in C++ namespaces
On 4/5/2014 2:55 PM, Michel Fortin wrote: I like this idea. But... should this potentially useful thing really be restricted to extern C++ things? I've seen at least one attempt to create a namespace using what D currently offers [1], and frankly something like the above would make much more sense than a class no one can instantiate. I can't escape the feeling that if you're trying to do namespaces in D, you're doing something worng. I feel that C++ messed up namespace design because: 1. namespaces are not closed 2. they have no relationship with modules which has wound up forcing the addition of Yet Another Design when imports and modules are added to C++.
Re: Specifying C++ symbols in C++ namespaces
Michel Fortin: Here's a suggestion: @namespace A.B { // can create two levels at once, yeah! void foo(); void bar(); } @namespace C { void foo(); } Make those C++ declarations, it does not look too foreign anymore: extern (C++) @namespace A.B { void foo(); void bar(); } extern (C++) @namespace C { void foo(); } I suggest to keep the access to C++ namespaces as a feature for interoperability only, and to have no namespaces in D. Bye, bearophile
Re: Specifying C++ symbols in C++ namespaces
On 2014-04-05 20:47:32 +, Walter Bright newshou...@digitalmars.com said: Yes, this seems to be a fatal flaw. Another design that has evolved from these discussions and my discussions with Andrei on it: extern (C++, namespace = A.B) { void foo(); void bar(); } extern (C++, namespace = C) void foo(); bar(); // works A.B.bar(); // works foo(); // error: ambiguous C.foo(); // works alias C.foo foo; foo(); // works, calling C.foo() What if you also have a C++ foo at global scope? module cpptest; extern (C++) void foo(); extern (C++, namespace = A) void foo(); foo(); // ambiguous A.foo(); // works .foo(); // works? cpptest.foo(); // works? Does these two last lines make sense? -- Michel Fortin michel.for...@michelf.ca http://michelf.ca
Re: Specifying C++ symbols in C++ namespaces
On 4/5/2014 6:26 PM, Michel Fortin wrote: What if you also have a C++ foo at global scope? It'll work exactly the same as import does. module cpptest; extern (C++) void foo(); extern (C++, namespace = A) void foo(); foo(); // ambiguous A.foo(); // works .foo(); // works? Yes. cpptest.foo(); // works? Yes. Does these two last lines make sense? Just as much sense as: module bar; void foo(); .foo(); // works bar.foo(); // works Namespace lookup rules would be exactly the same as for imports and mixin templates.
Re: Specifying C++ symbols in C++ namespaces
Walter Bright wrote in message news:lhi1lt$269h$1...@digitalmars.com... Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } This seems misleading to readers of future code. - An extern (C++) function lets you use a C++ function. - An extern (C++) interface lets you use a C++ interface (declared as a class, as is always the case in C++). - An extern (C++) template lets you use a C++... namespace? On Thursday, 3 April 2014 at 11:19:53 UTC, Daniel Murphy wrote: Why not just pragma(cpp_namespace, outer) { pragma(cpp_namespace, inner) { extern(C++) void func(); } } This really has only one obvious interpretation (the correct one), and seems to be a rather harmless addition to the language. It also fulfills the goal of allowing access to C++ libraries without cluttering D with C++ language features. I don't want to have to explain to my students the difference between modules D templates and C++ namespace templates (it reminds me of old- and new-style classes in Python 2).
Re: Specifying C++ symbols in C++ namespaces
On 4/3/2014 5:47 PM, deadalnix wrote: I'm not familiar with usual C++ mangling as much as D. Are template and namespace mangled the same way ? No.
Re: Specifying C++ symbols in C++ namespaces
Late to the thread, my short opinion: extern(C++ namespace::path) looks best. It should only affect mangling and have no impact on fully qualified name on D side. Most KISS solution I have read in the thread.
Re: Specifying C++ symbols in C++ namespaces
On 4/3/14, 11:59 PM, Mason McGill wrote: Walter Bright wrote in message news:lhi1lt$269h$1...@digitalmars.com... Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } This seems misleading to readers of future code. - An extern (C++) function lets you use a C++ function. - An extern (C++) interface lets you use a C++ interface (declared as a class, as is always the case in C++). - An extern (C++) template lets you use a C++... namespace? On Thursday, 3 April 2014 at 11:19:53 UTC, Daniel Murphy wrote: Why not just pragma(cpp_namespace, outer) { pragma(cpp_namespace, inner) { extern(C++) void func(); } } This really has only one obvious interpretation (the correct one), and seems to be a rather harmless addition to the language. It also fulfills the goal of allowing access to C++ libraries without cluttering D with C++ language features. I don't want to have to explain to my students the difference between modules D templates and C++ namespace templates (it reminds me of old- and new-style classes in Python 2). The above well describes my first reaction to the syntax (except the part about having students). And my second reaction too, in fact.
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 12:34:15 UTC, Dicebot wrote: Late to the thread, my short opinion: extern(C++ namespace::path) looks best. It should only affect mangling and have no impact on fully qualified name on D side. Most KISS solution I have read in the thread. I actually remember almost trying this syntax before reading this thread. It's definitely intuitive, and it KIS. Though, may I suggest extern(C++, namespace::path) or extern(C++, namespace, path) keeping in line with __traits and pragma?
Re: Specifying C++ symbols in C++ namespaces
On 03.04.2014 00:07, Walter Bright wrote: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } It would be accessed in D by: nspace!().foo(); A possible enhancement would be to allow (for all templates with no parameters): nspace.foo(); Note that: template nspace() { extern (C++) int foo(); } would not put foo() in a C++ namespace, although it would still be accessed from D as: nspace.foo(); One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. I have to say I like Robert Clipsham's idea best: extern(C++) module nspace { int foo(); // Is this also extern(C++)? I think it should be. } extern(C++) module nspace { module innernspace { int bar(); // Also extern(C++), if we follow the example above. } } I haven't the foggiest idea how C++ modules are supposed to work, so there might be clashes with those somehow? -- Simen
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 18:51:21 UTC, Simen Kjærås wrote: I have to say I like Robert Clipsham's idea best: extern(C++) module nspace { int foo(); // Is this also extern(C++)? I think it should be. } extern(C++) module nspace { module innernspace { int bar(); // Also extern(C++), if we follow the example above. } } All solutions based on binding extern(C++) to some D qualification entity are bad because they confuse reader into thinking that `bar` is actually `nspace.innerspace.bar` and that should never happen.
Re: Specifying C++ symbols in C++ namespaces
On 04.04.2014 20:54, Dicebot wrote: On Friday, 4 April 2014 at 18:51:21 UTC, Simen Kjærås wrote: I have to say I like Robert Clipsham's idea best: extern(C++) module nspace { int foo(); // Is this also extern(C++)? I think it should be. } extern(C++) module nspace { module innernspace { int bar(); // Also extern(C++), if we follow the example above. } } All solutions based on binding extern(C++) to some D qualification entity are bad because they confuse reader into thinking that `bar` is actually `nspace.innerspace.bar` and that should never happen. I'm not entirely sure I follow you here. Is this what you mean? extern(C++) module nspace { int foo(); } void main() { foo();// Either this does not work, (#1) nspace.foo(); // or this does not work. (#2) } If so, is that really bad? I'd say the better choice is to make #2 work, as then #1 can be made to work with a simple alias: alias foo = nspace.foo; If I'm far off into the fields of ignorance now, care to show me the way to a better understanding? -- Simen
Re: Specifying C++ symbols in C++ namespaces
On 4/4/2014 5:34 AM, Dicebot wrote: Late to the thread, my short opinion: extern(C++ namespace::path) looks best. It should only affect mangling and have no impact on fully qualified name on D side. Most KISS solution I have read in the thread. Fails because: C++: namespace S { namespace T { int foo(); namespace U { int foo(); } } } D: extern (C++, S::T) { int foo(); extern (C++, U) { int foo(); } } foo(); // error, ambiguous, which one? S.T.foo(); // S undefined
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 19:43:56 UTC, Walter Bright wrote: foo(); // error, ambiguous, which one? S.T.foo(); // S undefined I want explicit namespaces S::T::foo().
Re: Specifying C++ symbols in C++ namespaces
On 4/4/2014 1:00 PM, Ola Fosheim Grøstad ola.fosheim.grostad+dl...@gmail.com wrote: I want explicit namespaces S::T::foo(). We already have a scope operator, '.', don't need another one.
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 19:43:56 UTC, Walter Bright wrote: C++: namespace S { namespace T { int foo(); namespace U { int foo(); } } } D: extern (C++, S::T) { int foo(); extern (C++, U) { int foo(); } } foo(); // error, ambiguous, which one? S.T.foo(); // S undefined Why would we need new ways of declaring scopes in D? Overriding the external mangling should be sufficient? If there are collisions you can use any type of scope you prefer to avoid the issue, modules, structs, templates, even functions or blocks... void fun1() { extern (C++, S::T) int foo();} void fun2() { extern (C++, S::T::U) int foo();} extern (C++, S::T::U) int foo(); struct test { extern (C++, S::T) int foo();}
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 20:06:49 UTC, Walter Bright wrote: We already have a scope operator, '.', don't need another one. It is more clear to the reader that it is an external namespace and you avoid renaming because then C++ has it's own namespace in D reducing the chances of clashes. But it's a minor issue, although I think it is important for long term maintainability of code to easily discriminate between C++ function calls (which tend to be supportive lower level libraries/engines) and D function calls (which tend to be higher level code). When you do contract work on many projects for different small businesses, you often get requests for modifications/additions 1-2 times a year or so. The less chance of code misinterpretation, the better.
Re: Specifying C++ symbols in C++ namespaces
Tove: Why would we need new ways of declaring scopes in D? Overriding the external mangling should be sufficient? If there are collisions you can use any type of scope you prefer to avoid the issue, modules, structs, templates, even functions or blocks... void fun1() { extern (C++, S::T) int foo();} void fun2() { extern (C++, S::T::U) int foo();} extern (C++, S::T::U) int foo(); struct test { extern (C++, S::T) int foo();} This seems promising, but this idea needs to become simpler. Bye, bearophile
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 19:43:56 UTC, Walter Bright wrote: Fails because: C++: namespace S { namespace T { int foo(); namespace U { int foo(); } } } D: extern (C++, S::T) { int foo(); extern (C++, U) { int foo(); } } foo(); // error, ambiguous, which one? S.T.foo(); // S undefined I don't feel this is a problem. Such foo's should be disambugated by D tools, which means using different modules. Exact matching between C++ and D sources is impossible anyway, it is not worth complicating D qualification system for that.
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 19:33:34 UTC, Simen Kjærås wrote: I'm not entirely sure I follow you here. Is this what you mean? extern(C++) module nspace { int foo(); } void main() { foo();// Either this does not work, (#1) nspace.foo(); // or this does not work. (#2) } If so, is that really bad? I'd say the better choice is to make #2 work, as then #1 can be made to work with a simple alias: alias foo = nspace.foo; If I'm far off into the fields of ignorance now, care to show me the way to a better understanding? #2 should not compile. D currently does not have any notion of namespaces other than modules / aggregates and I am against introducing those just for the sake of interfacing with C++.
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 21:39:01 UTC, bearophile wrote: Tove: Why would we need new ways of declaring scopes in D? Overriding the external mangling should be sufficient? If there are collisions you can use any type of scope you prefer to avoid the issue, modules, structs, templates, even functions or blocks... void fun1() { extern (C++, S::T) int foo();} void fun2() { extern (C++, S::T::U) int foo();} extern (C++, S::T::U) int foo(); struct test { extern (C++, S::T) int foo();} This seems promising, but this idea needs to become simpler. Bye, bearophile This seems like it would be simple if it came with a recommended style for library wrappers, e.g. // C++ namespace A { namespace B { void f1(); void f2(); } namespace C { void f3(); void f4(); } } // D struct A { struct B { extern(C++, A, B): static void f1(); static void f2(); } struct C { extern(C++, A, C): static void f3(); static void f4(); } } This can be easily generated by hand or with something like SWIG, and keeps the semantics of extern consistent throughout the language (it still only affects the ABI). This also keeps things simple for users who just want to call one function. // D void callF1() { extern(C++, A, B) void f1(); f1(); } I used , instead of :: because it avoids adding a new token, but that's more of an aesthetic issue.
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 07:06:30 UTC, Walter Bright wrote: On 4/3/2014 5:47 PM, deadalnix wrote: I'm not familiar with usual C++ mangling as much as D. Are template and namespace mangled the same way ? No. Then that is a bad idea.
Re: Specifying C++ symbols in C++ namespaces
On Friday, 4 April 2014 at 22:17:45 UTC, Dicebot wrote: On Friday, 4 April 2014 at 19:33:34 UTC, Simen Kjærås wrote: I'm not entirely sure I follow you here. Is this what you mean? extern(C++) module nspace { int foo(); } void main() { foo();// Either this does not work, (#1) nspace.foo(); // or this does not work. (#2) } If so, is that really bad? I'd say the better choice is to make #2 work, as then #1 can be made to work with a simple alias: alias foo = nspace.foo; If I'm far off into the fields of ignorance now, care to show me the way to a better understanding? #2 should not compile. D currently does not have any notion of namespaces other than modules / aggregates and I am against introducing those just for the sake of interfacing with C++. templates, function bodies, block statements, ...
Re: Specifying C++ symbols in C++ namespaces
On Wednesday, 2 April 2014 at 22:06:53 UTC, Walter Bright wrote: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } @namespace(nspace) extern (C++) { int foo(); } One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. If we have partial C++ bindings, why not have partial template bindings with a subset of features already existing in D? With that you would only need to implement mangling and linking. An interesting and simple enough use case is casting: extern(C++) T my_cast(T,U)(U); extern(C++) interface A{} extern(C++) interface B:A{} A a; B b = my_cast!B(a);
Re: Specifying C++ symbols in C++ namespaces
On Wednesday, 2 April 2014 at 22:06:53 UTC, Walter Bright wrote: A possible enhancement would be to allow (for all templates with no parameters): nspace.foo(); std.string - does it refer to phobos module or C++ string?
Re: Specifying C++ symbols in C++ namespaces
On 4/3/14, Walter Bright newshou...@digitalmars.com wrote: A possible enhancement would be to allow (for all templates with no parameters): nspace.foo(); My only problem with this is how it will affect existing code. E.g.: template take(alias templ) { } template take(T) { } template Empty() { struct Empty { } } take!Empty; // which overload of take is instantiated?
Re: Specifying C++ symbols in C++ namespaces
On 2014-04-03 03:48:18 +, Walter Bright newshou...@digitalmars.com said: On 4/2/2014 7:14 PM, Michel Fortin wrote: That's a contrived example. Not at all. The whole point of using namespaces in C++ is to introduce a scope. And the whole point of scopes is to have the same name in different scopes represent different objects. Perhaps I'm wrong, but I'd assume the general use case is that all functions in a module will come from the same C++ namespace. I believe that is an incorrect assumption. C++ namespaces were specifically (and wrongly, in my not so humble opinion, but there it is) not designed to be closed, nor have any particular relationship with modules. Alternatively you can use another module for the other namespace. Forcing C++ code that exists in a single file to be split up among multiple D files is inflicting unnecessary punishment on the poor guy trying to justify migrating to D. Ok, let's assume that we actually want to reproduce the C++ file structure then. Let us have a C++ project, with two files. I'll temporarily use the 'namespace' keyword on the D side until we can decide on how to best represent a namespace: module foo; extern (C++): namespace S { namespace T { int foo(); namespace U { int foo(); } } } module bar; extern (C++): namespace S { namespace T { int bar(); namespace U { int bar(); } } } Now let's use those: module main; import foo; import bar; void main() { S.T.foo(); S.T.U.bar(); } But how does the lookup for those functions work? If we use structs or templates to represent those namespaces in D then you'll have to specify the module name to disambiguate the struct/template itself, and the namespace just becomes a nuisance you have to repeat over and over: void main() { .foo.S.T.foo(); .bar.S.T.U.bar(); } Here I'd argue that having whole-module namespaces in D makes no sense. So let's retry by peeling the S.T part of the namespace: module foo; extern (C++, S.T): int foo(); namespace U { int foo(); } module bar; extern (C++, S.T): int bar(); namespace U { int bar(); } module main; import foo; import bar; void main() { foo(); .bar.U.bar(); } Better. Still, if you want C++ namespaces to work nicely, you'll have to introduce first class namespace support in D. That means that identical namespaces are merged into each other when you import modules that contain them. It'd allow you to write this: void main() { foo(); U.bar(); } Still, I'm not convinced that'd be terribly helpful. Namespaces in D would make it easier to declare things 1:1 for sure, but anything that depends on Koenig lookup[1] will be broken in D. It could even be silently broken as no Koenig lookup means another function not in a namespace could be used silently instead of the expected one in a namespace (assuming a naive port of some C++ code). [1]: https://en.wikipedia.org/wiki/Argument-dependent_name_lookup I'd tend to simply implement extern(C++, namespace.here), which should work fine to wrap single-namespace cpp files, and wait to see what are the actual friction points before introducing more (people can experiment with structs or other modules meanwhile). -- Michel Fortin michel.for...@michelf.ca http://michelf.ca
Re: Specifying C++ symbols in C++ namespaces
V Thu, 3 Apr 2014 06:36:54 -0400 Michel Fortin michel.for...@michelf.ca napsáno: On 2014-04-03 03:48:18 +, Walter Bright newshou...@digitalmars.com said: On 4/2/2014 7:14 PM, Michel Fortin wrote: That's a contrived example. Not at all. The whole point of using namespaces in C++ is to introduce a scope. And the whole point of scopes is to have the same name in different scopes represent different objects. Perhaps I'm wrong, but I'd assume the general use case is that all functions in a module will come from the same C++ namespace. I believe that is an incorrect assumption. C++ namespaces were specifically (and wrongly, in my not so humble opinion, but there it is) not designed to be closed, nor have any particular relationship with modules. Alternatively you can use another module for the other namespace. Forcing C++ code that exists in a single file to be split up among multiple D files is inflicting unnecessary punishment on the poor guy trying to justify migrating to D. Ok, let's assume that we actually want to reproduce the C++ file structure then. Let us have a C++ project, with two files. I'll temporarily use the 'namespace' keyword on the D side until we can decide on how to best represent a namespace: module foo; extern (C++): namespace S { namespace T { int foo(); namespace U { int foo(); } } } module bar; extern (C++): namespace S { namespace T { int bar(); namespace U { int bar(); } } } Now let's use those: module main; import foo; import bar; void main() { S.T.foo(); S.T.U.bar(); } But how does the lookup for those functions work? If we use structs or templates to represent those namespaces in D then you'll have to specify the module name to disambiguate the struct/template itself, and the namespace just becomes a nuisance you have to repeat over and over: void main() { .foo.S.T.foo(); .bar.S.T.U.bar(); } Here I'd argue that having whole-module namespaces in D makes no sense. So let's retry by peeling the S.T part of the namespace: module foo; extern (C++, S.T): int foo(); namespace U { int foo(); } module bar; extern (C++, S.T): int bar(); namespace U { int bar(); } module main; import foo; import bar; void main() { foo(); .bar.U.bar(); } Better. Still, if you want C++ namespaces to work nicely, you'll have to introduce first class namespace support in D. That means that identical namespaces are merged into each other when you import modules that contain them. It'd allow you to write this: void main() { foo(); U.bar(); } Still, I'm not convinced that'd be terribly helpful. Namespaces in D would make it easier to declare things 1:1 for sure, but anything that depends on Koenig lookup[1] will be broken in D. It could even be silently broken as no Koenig lookup means another function not in a namespace could be used silently instead of the expected one in a namespace (assuming a naive port of some C++ code). [1]: https://en.wikipedia.org/wiki/Argument-dependent_name_lookup I'd tend to simply implement extern(C++, namespace.here), which should work fine to wrap single-namespace cpp files, and wait to see what are the actual friction points before introducing more (people can experiment with structs or other modules meanwhile). I think we should distinguish modules lookup from namespaces lookup. Something like this: A.B.foo() // call foo function from module/struct/class A and B #A.#B.foo // call foo function from namespaces A and B or A::B.foo // call foo function from namespaces A and B or /A/B.foo // call foo function from namespaces A and B
Re: Specifying C++ symbols in C++ namespaces
Walter Bright wrote in message news:lhi1lt$269h$1...@digitalmars.com... Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } This is really ugly and complicated. Why not just pragma(cpp_namespace, outer) { pragma(cpp_namespace, inner) { extern(C++) void func(); } } which is trivial to implement and doesn't require parser or semantic changes? Adding syntax for actual namespaces to D is a different beast and IMO not worthwhile.
Re: Specifying C++ symbols in C++ namespaces
On 03/04/14 00:07, Walter Bright wrote: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } It would be accessed in D by: nspace!().foo(); A possible enhancement would be to allow (for all templates with no parameters): nspace.foo(); Note that: template nspace() { extern (C++) int foo(); } would not put foo() in a C++ namespace, although it would still be accessed from D as: nspace.foo(); One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. I like using a UDA or pragma better: @namespace(nspace) { extern (C++) int foo (); } Or pragma(cpp_namespace, nspace) { extern (C++) int foo (); } Then it's also possible to use this syntax: @namespace(nspace): extern (C++) int foo (); The only advantage I can see with using template is that templates can be mixed in, it would be similar to the using declarative in C++. -- /Jacob Carlborg
Re: Specifying C++ symbols in C++ namespaces
I am not sure what is the best option, but it should be readable and obvious. So I might prefer to just have :: if possible. Somewhat annoying and verbose, so I am not sure about this, but the advantage is that it is easy to see what is C++ and what is D function calls.
Re: Specifying C++ symbols in C++ namespaces
On Thursday, 3 April 2014 at 03:48:08 UTC, Walter Bright wrote: Alternatively you can use another module for the other namespace. Forcing C++ code that exists in a single file to be split up among multiple D files is inflicting unnecessary punishment on the poor guy trying to justify migrating to D. A solution could be to allow this: module foo { module bar { // equivalent to foo/bar.d } } extern(C++) module bar { // Equivalent to namespace bar {} in C++ } Note that Rust does something similar to this to allow multiple modules to be defined in a single file (though Rust also doesn't have the correspondence between filesystem location and module like D does - perhaps this is acceptable with the introduction of package.d?) Robert
Re: Specifying C++ symbols in C++ namespaces
On 4/3/2014 4:06 AM, Daniel Kozák wrote: I think we should distinguish modules lookup from namespaces lookup. Something like this: A.B.foo() // call foo function from module/struct/class A and B #A.#B.foo // call foo function from namespaces A and B or A::B.foo // call foo function from namespaces A and B or /A/B.foo // call foo function from namespaces A and B Please, no!
Re: Specifying C++ symbols in C++ namespaces
On 4/3/2014 3:36 AM, Michel Fortin wrote: I'd tend to simply implement extern(C++, namespace.here), which should work fine to wrap single-namespace cpp files, and wait to see what are the actual friction points before introducing more (people can experiment with structs or other modules meanwhile). You have a good point in that to go all the way with namespaces, we'd have to implement Koenig lookup and support insertion of names into previous namespaces. I can't see this happening in D. But I don't see that as much of an argument to not do simple scoping with namespace lookup.
Re: Specifying C++ symbols in C++ namespaces
On Thursday, 3 April 2014 at 19:44:02 UTC, Walter Bright wrote: On 4/3/2014 4:06 AM, Daniel Kozák wrote: I think we should distinguish modules lookup from namespaces lookup. Something like this: A.B.foo() // call foo function from module/struct/class A and B #A.#B.foo // call foo function from namespaces A and B or A::B.foo // call foo function from namespaces A and B or /A/B.foo // call foo function from namespaces A and B Please, no! Ok, just an idea :)
Re: Specifying C++ symbols in C++ namespaces
On 4/3/14, 4:19 AM, Daniel Murphy wrote: Walter Bright wrote in message news:lhi1lt$269h$1...@digitalmars.com... Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } This is really ugly and complicated. Why not just pragma(cpp_namespace, outer) { pragma(cpp_namespace, inner) { extern(C++) void func(); } } which is trivial to implement and doesn't require parser or semantic changes? I don't quite see how one is ugly and complicated and the other is... pretty and simple? Anyhow de gustibus. Adding syntax for actual namespaces to D is a different beast and IMO not worthwhile. Agreed. Andrei
Re: Specifying C++ symbols in C++ namespaces
On 2014-04-03 19:43:23 +, Walter Bright newshou...@digitalmars.com said: On 4/3/2014 3:36 AM, Michel Fortin wrote: I'd tend to simply implement extern(C++, namespace.here), which should work fine to wrap single-namespace cpp files, and wait to see what are the actual friction points before introducing more (people can experiment with structs or other modules meanwhile). You have a good point in that to go all the way with namespaces, we'd have to implement Koenig lookup and support insertion of names into previous namespaces. I can't see this happening in D. Me neither. But I don't see that as much of an argument to not do simple scoping with namespace lookup. What I'm saying is that it should be optional to create a new scope to declare a C++ function from a namespace. In other words you need to be able to put the function at module scope in D. -- Michel Fortin michel.for...@michelf.ca http://michelf.ca
Re: Specifying C++ symbols in C++ namespaces
On Thursday, 3 April 2014 at 11:19:53 UTC, Daniel Murphy wrote: Walter Bright wrote in message news:lhi1lt$269h$1...@digitalmars.com... Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } This is really ugly and complicated. Why not just pragma(cpp_namespace, outer) { pragma(cpp_namespace, inner) { extern(C++) void func(); } } which is trivial to implement and doesn't require parser or semantic changes? Adding syntax for actual namespaces to D is a different beast and IMO not worthwhile. IMO I don't think pragmas are meant to this kind of uses, extern(C++) already exists and makes more sense.
Re: Specifying C++ symbols in C++ namespaces
On Thu, Apr 03, 2014 at 12:43:59PM -0700, Walter Bright wrote: On 4/3/2014 4:06 AM, Daniel Kozák wrote: I think we should distinguish modules lookup from namespaces lookup. Something like this: A.B.foo() // call foo function from module/struct/class A and B #A.#B.foo // call foo function from namespaces A and B or A::B.foo // call foo function from namespaces A and B or /A/B.foo // call foo function from namespaces A and B Please, no! The current situation where module/scope qualifiers clash with UFCS sux, though. static import std.algorithm; ... auto myRange = ...; //myRange.std.algorithm.find(...); // NG :-( alias find = std.algorithm.find; myRange.find(...); // OK But this is kinda tangential to this topic. :P T -- My program has no bugs! Only undocumented features...
Re: Specifying C++ symbols in C++ namespaces
On Wednesday, 2 April 2014 at 22:06:53 UTC, Walter Bright wrote: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } It would be accessed in D by: nspace!().foo(); A possible enhancement would be to allow (for all templates with no parameters): nspace.foo(); Note that: template nspace() { extern (C++) int foo(); } would not put foo() in a C++ namespace, although it would still be accessed from D as: nspace.foo(); One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. I'm not familiar with usual C++ mangling as much as D. Are template and namespace mangled the same way ?
Re: Specifying C++ symbols in C++ namespaces
Andrei Alexandrescu wrote in message news:lhkebg$1i1p$1...@digitalmars.com... extern (C++) template nspace() { int foo(); } This is really ugly and complicated. I don't quite see how one is ugly and complicated and the other is... pretty and simple? Anyhow de gustibus. Stuff inside the template will only be instantiated when used. That's fine when it's just a prototype of a C++ function to be called from D, but much less useful when the implementation is in D and the use is from C++. It can conflict with the eponymous template syntax - D would not be able to tell the difference between a templated function and a function inside a namespace with the same name. It forces this organisation for all symbols that use C++ namespaces. If you define functions in the same namespace in different modules the template symbols will conflict and you will have to use fully-qualified names. On the other side, in D modules are used for symbol organisation. It's powerful enough that you can get namespace::function to match library.module.function (and I expect you can force use of the namespace through clever use of static renamed imports). The missing part is getting the mangling right, and a pragma is the least intrusive way I can imagine to do that.
Specifying C++ symbols in C++ namespaces
Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } It would be accessed in D by: nspace!().foo(); A possible enhancement would be to allow (for all templates with no parameters): nspace.foo(); Note that: template nspace() { extern (C++) int foo(); } would not put foo() in a C++ namespace, although it would still be accessed from D as: nspace.foo(); One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that.
Re: Specifying C++ symbols in C++ namespaces
Seems alright. The only downside I can think of is that the namespace wouldn't be semantically analysed until you first try to use it, as it's a template.
Re: Specifying C++ symbols in C++ namespaces
Walter Bright: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } I suggest to brainstorm the syntax some more time, because someone could be able to invent a better syntax. Some seeds: extern (C++(nspace)) { int foo(); } extern (C++) struct nspace { int foo(); } extern (C++)(nspace) { int foo(); } extern (C++ nspace) { int foo(); } Bye, bearophile
Re: Specifying C++ symbols in C++ namespaces
And what about something like static struct? It seems more natural and less hacky to me.
Re: Specifying C++ symbols in C++ namespaces
On Wednesday, 2 April 2014 at 22:33:21 UTC, bearophile wrote: Walter Bright: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } I suggest to brainstorm the syntax some more time, because someone could be able to invent a better syntax. Some seeds: extern (C++(nspace)) { int foo(); } extern (C++) struct nspace { int foo(); } extern (C++)(nspace) { int foo(); } extern (C++ nspace) { int foo(); } Bye, bearophile extern (C++) module nspace;
Re: Specifying C++ symbols in C++ namespaces
Xiaoxi: extern (C++) module nspace; They plan to add some kind of modules to C++ in few years :-( So this risks semantic clashes. Bye, bearophile
Re: Specifying C++ symbols in C++ namespaces
On Wednesday, 2 April 2014 at 22:06:53 UTC, Walter Bright wrote: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } It would be accessed in D by: nspace!().foo(); A possible enhancement would be to allow (for all templates with no parameters): nspace.foo(); Note that: template nspace() { extern (C++) int foo(); } would not put foo() in a C++ namespace, although it would still be accessed from D as: nspace.foo(); One downside of this proposal is that if we ever (perish the thought!) attempted to interface to C++ templates, this design would preclude that. Walter, some on this list have not been around long enough to understand the motivation for this. Could you please summarize the problem and how this addresses it? Is this for interfacing D to C++, or a way to bring namespace semantics to D? Mike
Re: Specifying C++ symbols in C++ namespaces
On Wednesday, 2 April 2014 at 22:33:21 UTC, bearophile wrote: Walter Bright: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } I suggest to brainstorm the syntax some more time, because someone could be able to invent a better syntax. Some seeds: ... extern (C++)(nspace) { int foo(); } extern (C++ nspace) { int foo(); } Bye, bearophile I definitely like the last two. Small and to the point. But where nspace is a wrapper 'static struct' essentially. So: nspace.foo()
Re: Specifying C++ symbols in C++ namespaces
On Wednesday, 2 April 2014 at 23:04:58 UTC, Mike wrote: On Wednesday, 2 April 2014 at 22:06:53 UTC, Walter Bright wrote: Here's Andrei's proposal: extern (C++) template nspace() { int foo(); } Is this for interfacing D to C++, or a way to bring namespace semantics to D? Well, I'm assuming this is specifically for interfacing D with C++ given the 'extern (C++)' attribution. In that case, I think the proposal abuses the 'template' keyword for something that's not really a template. In that case, I find the syntax proposed by bearophile to be far better... extern (C++ nspace) { int foo(); } ...although I would even prefer it be even more explicit... extern (C++ namespace nspace) { int foo(); } I'd also be interested in hearing the arguments against the UDAs and pragmas proposed in the following two links: * https://d.puremagic.com/issues/show_bug.cgi?id=7961 * https://github.com/D-Programming-Language/dmd/pull/2767 The pragma is especially nice since this isn't really a D thing, although bearophile's proposed syntax is hard to argue against. Mike
Re: Specifying C++ symbols in C++ namespaces
On 4/2/2014 3:33 PM, bearophile wrote: I suggest to brainstorm the syntax some more time, because someone could be able to invent a better syntax. Some seeds: extern (C++(nspace)) { int foo(); } I considered that, but it fails because: C++: namespace S { namespace T { int foo(); namespace U { int foo(); } } } D: extern (C++, S.T) { int foo(); extern (C++, U) { int foo(); } } foo(); // error, ambiguous, which one? S.T.foo(); // S undefined extern (C++) struct nspace { int foo(); } Fails because a struct as struct and struct as namespace are not distinguishable.
Re: Specifying C++ symbols in C++ namespaces
On 4/2/2014 3:30 PM, monnoroch wrote: And what about something like static struct? It seems more natural and less hacky to me. Because C++ mangles static member functions of structs differently from members of namespaces.
Re: Specifying C++ symbols in C++ namespaces
On 4/2/2014 4:04 PM, Mike wrote: Walter, some on this list have not been around long enough to understand the motivation for this. Could you please summarize the problem and how this addresses it? Is this for interfacing D to C++, or a way to bring namespace semantics to D? See the earlier thread entitled: C++ interface. started yesterday.
Re: Specifying C++ symbols in C++ namespaces
Walter Bright: I considered that, but it fails because: C++: namespace S { namespace T { int foo(); namespace U { int foo(); } } } D: extern (C++, S.T) { int foo(); extern (C++, U) { int foo(); } } foo(); // error, ambiguous, which one? S.T.foo(); // S undefined Then is the idea of extern(C++) module by Xiaoxi usable in some way? Bye, bearophile
Re: Specifying C++ symbols in C++ namespaces
On Thursday, 3 April 2014 at 01:06:25 UTC, Walter Bright wrote: Because C++ mangles static member functions of structs differently from members of namespaces. What i meant is not static functions and members of a struct, but a static struct as a concept of a struct, whith can only contain a static stuff. C++ has no such concept, but essentually static struct === namespace. Consider this: extern(C++) static struct A { static struct B { struct X {} int foo(X); } } A.B.foo(A.B.X());
Re: Specifying C++ symbols in C++ namespaces
Also, D already has scope classes, so why not create full featured class bindings? Suppose, i have this: class A { private: int x; public: A(int x_) : x(x_) {} A(const A v) : x(v.x) {} ~A() {} }; Why not interfase those as: extern (C++) { struct A { int x; this(int x_); // call c++ A::A(int) this(this); // call c++ A::A(const A) ~this(); // call c++ A::~A() } } I mean, methods in c++ are just like functions in namespaces with first T* argument, so this is also just mangling problem; and all those constructors and destructors are not something special either. What stops to do that? If value semantics isn't appropriate, user, who writes D interface can just do it in scope class. Maby discussing that would also do some good.
Re: Specifying C++ symbols in C++ namespaces
Or even the simplier way. Just do: extern(C++) struct A { int x; A A(int x_); A A(ref const(A) v); void ~A(A*); } And call those methods manually: A obj = A.A(1); A obj1 = A.A(obj); A.~A(obj); A.~A(obj1); The problem here it to distinguish real static methods from fake ones. But we can actually make user mark real static methods as static.
Re: Specifying C++ symbols in C++ namespaces
On 2014-04-03 01:09:43 +, Walter Bright newshou...@digitalmars.com said: I considered that, but it fails because: C++: namespace S { namespace T { int foo(); namespace U { int foo(); } } } D: extern (C++, S.T) { int foo(); extern (C++, U) { int foo(); } } foo(); // error, ambiguous, which one? S.T.foo(); // S undefined That's a contrived example. Perhaps I'm wrong, but I'd assume the general use case is that all functions in a module will come from the same C++ namespace. For the contrived example above, I think it's fair you have to use a contrived solution: module s.t; extern (C++, S.T): int foo(); struct U { static extern (C++, S.T.U): int foo(); } Alternatively you can use another module for the other namespace. -- Michel Fortin michel.for...@michelf.ca http://michelf.ca
Re: Specifying C++ symbols in C++ namespaces
On 4/2/2014 7:14 PM, Michel Fortin wrote: On 2014-04-03 01:09:43 +, Walter Bright newshou...@digitalmars.com said: I considered that, but it fails because: C++: namespace S { namespace T { int foo(); namespace U { int foo(); } } } D: extern (C++, S.T) { int foo(); extern (C++, U) { int foo(); } } foo(); // error, ambiguous, which one? S.T.foo(); // S undefined That's a contrived example. Not at all. The whole point of using namespaces in C++ is to introduce a scope. And the whole point of scopes is to have the same name in different scopes represent different objects. Perhaps I'm wrong, but I'd assume the general use case is that all functions in a module will come from the same C++ namespace. I believe that is an incorrect assumption. C++ namespaces were specifically (and wrongly, in my not so humble opinion, but there it is) not designed to be closed, nor have any particular relationship with modules. For the contrived example above, I think it's fair you have to use a contrived solution: I don't believe that punishing C++ users who dare to try D is the path to success for D :-) Alternatively you can use another module for the other namespace. Forcing C++ code that exists in a single file to be split up among multiple D files is inflicting unnecessary punishment on the poor guy trying to justify migrating to D.