Search code examples
d

splitting declaration from definition


I really want to use D because its language constructions do so many things I care about better than C++, but the almost-forced GC (issue handled [sort of] here), slightly less powerful operator overloading (except opDispatch. opDispatch is sexy), and the following issue are kinda turning me off.

Is it possible in D to split a method declaration from a definition? If so, how? If not, why?

Motivating example for 'how': to provide a small header file of interface functions next to a binary object, as with a C header and library, for the sake of hiding the implementation away from the eyes of a writer of user code. Preference: without depending on whether or not the user code has hacked away the garbage collector or is simply compiling without druntime (such as this found in the comments here).


Solution

  • If I write a D file like this one: http://arsdnet.net/dcode/iface/test.d and you compile with dmd -c, you'll see it goes without errors; that's a valid D file. The language allows you to write function prototypes without implementations.

    A .di file is just like that, it just has a different file name.

    Then given main: http://arsdnet.net/dcode/main.d if you compile dmd main, it will automatically search for iface/test.d when it sees "import iface.test;", find that .d file, or the .di if you rename it but same thing, and get your interface definition.

    dmd main will fail with a linker error, so we need to implement it: http://arsdnet.net/dcode/impl.d Note: the impl does NOT import the module, so it never checks the other file. Keeping the .di and .d files in sync is one of the tricky parts here, unless you auto-generate the interface file, as undefined methods would give linker errors, but the order of methods is important: it must match, and so do the list of variables if there's any public ones. Otherwise, the usage code and the implementation code won't agree on the class' layout.

    Again, it does not check that automatically, the implementation file doesn't look at the "header" file at all, so this is a major difference from C++ where you write the header file once, then use it in both the usage program and the implementation file.

    You'll notice that the implementation file also lists the class, etc., too. D doesn't support the void MyClass::add(int a) {} syntax C++ has to write the method outside the class.

    As far as I know, there's no way to force the implementation file to look for the header, if you put both on the command line, you get: "Error: module iface.test from file iface/test.d conflicts with another module test from file impl.d"

    The way .di files are recommended to be used is to auto generate them with dmd -H. This reads the full implementation file and strips out the function bodies, leaving just the definitions. This part is probably the key thing when they say it is a feature of the compiler - the .di file is valid and standard D, but generated via a compiler option that doesn't necessarily need to be part of other compilers.