V Thu, 3 Apr 2014 06:36:54 -0400 Michel Fortin <michel.for...@michelf.ca> napsáno:
> On 2014-04-03 03:48:18 +0000, 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