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).


--
Michel Fortin
michel.for...@michelf.ca
http://michelf.ca

Reply via email to