www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function definition in multiple modules

reply Martin Drasar <drasar ics.muni.cz> writes:
Hi,

I have a class that implements a lot of interfaces and I would like to
separate the definition into different files, i.e. implementation of one
interface in one file. Something akin to this C++ code:

a.cpp:

class A
{
  void b();
  void c();
};

b.cpp:

void A::b() {}

c.cpp:

void A::c() {}

Is there a way to do it in D easily? Do I have to use UFCS?

Thanks,
Martin
Mar 29 2012
parent reply simendsjo <simendsjo gmail.com> writes:
On Thu, 29 Mar 2012 10:33:03 +0200, Martin Drasar <drasar ics.muni.cz>  
wrote:

 Hi,

 I have a class that implements a lot of interfaces and I would like to
 separate the definition into different files, i.e. implementation of one
 interface in one file. Something akin to this C++ code:

 a.cpp:

 class A
 {
   void b();
   void c();
 };

 b.cpp:

 void A::b() {}

 c.cpp:

 void A::c() {}

 Is there a way to do it in D easily? Do I have to use UFCS?

 Thanks,
 Martin
D has interface files, .di. These can be automatically generated by the compiler using the -H switch. So you code your class normally: a.d: class A { void a() {} void b() {} } $ dmd -H a.d $ cat a.di // D import file generated from 'a.d' class A { void a() { } void b() { } }
Mar 29 2012
parent reply Martin Drasar <drasar ics.muni.cz> writes:
On 29.3.2012 11:16, simendsjo wrote:
 
 D has interface files, .di. These can be automatically generated by the
 compiler using the -H switch.
 
 So you code your class normally:
 a.d:
 class A
 {
     void a() {}
     void b() {}
 }
 
 $ dmd -H a.d
 $ cat a.di
 // D import file generated from 'a.d'
 class A
 {
     void a()
 {
 }
     void b()
 {
 }
 }
Hi, I have probably not made myslef clear. Let's say I have this D code: interfaces.d: interface IA { void a(); } interface IB { void b(); } myfunkyclass.d: import interfaces; class X : IA, IB { void a() { } void b() { } } I would like to split the X class definition into two files. One file would implement methods of interface IA and another of interface IB. So it would be like this: myfunkyclassIA.d: class X : IA, IB { void a() { } } myfunkyclassIB.d: void b(X x) { } Except using UFCS in this case does not work... Martin
Mar 29 2012
parent reply simendsjo <simendsjo gmail.com> writes:
On Thu, 29 Mar 2012 11:31:57 +0200, Martin Drasar <drasar ics.muni.cz>  
wrote:

 On 29.3.2012 11:16, simendsjo wrote:
 D has interface files, .di. These can be automatically generated by the
 compiler using the -H switch.
(snip)
 I would like to split the X class definition into two files. One file
 would implement methods of interface IA and another of interface IB. So
 it would be like this:

 myfunkyclassIA.d:
 class X : IA, IB
 {
   void a()
   {
   }
 }

 myfunkyclassIB.d:
 void b(X x)
 {
 }

 Except using UFCS in this case does not work...

 Martin
Your looking for partial classes? D doesn't have this as far as I know. "alias this" should work for more than one value in the future, and then (I think) you should be able to do something like this: class XIB : IB {} class XIA : IA {} class X : IA, IB { XIA xia; XIB xib; alias xia this; alias xib this; } But you can also solve it with mixin templates: mixin template XIA { // all IA methods } mixin template XIB { // all IB methods } class X : IA, IB { mixin XIA!(); mixin XIB!(); }
Mar 29 2012
parent reply Martin Drasar <drasar ics.muni.cz> writes:
On 29.3.2012 12:02, simendsjo wrote:
 Your looking for partial classes? D doesn't have this as far as I know.
 
 "alias this" should work for more than one value in the future, and then
 (I think) you should be able to do something like this:
 
 class XIB : IB {}
 class XIA : IA {}
 class X : IA, IB {
   XIA xia;
   XIB xib;
   alias xia this;
   alias xib this;
 }
I was thinking about similar idea. But instead of alias this I intended to write something like this: class X : IA, IB { XIA xia; void iamethod() { xia.iamethod(); } ... } It is not very pretty though...
 But you can also solve it with mixin templates:
 mixin template XIA {
   // all IA methods
 }
 mixin template XIB {
   // all IB methods
 }
 
 class X : IA, IB {
   mixin XIA!();
   mixin XIB!();
 }
This would make the code separation easy to manage, but I am concerned about debugging. How is e.g. gdb able to debug mixins? I think I have read somewhere in the D or D-learn, that the dmd can produce the file with mixed-in code for the debugger, but I am not sure how to find it. Martin
Mar 29 2012
parent reply simendsjo <simendsjo gmail.com> writes:
On Thu, 29 Mar 2012 12:58:56 +0200, Martin Drasar <drasar ics.muni.cz>  
wrote:

 On 29.3.2012 12:02, simendsjo wrote:
 Your looking for partial classes? D doesn't have this as far as I know.

 "alias this" should work for more than one value in the future, and then
 (I think) you should be able to do something like this:

 class XIB : IB {}
 class XIA : IA {}
 class X : IA, IB {
   XIA xia;
   XIB xib;
   alias xia this;
   alias xib this;
 }
I was thinking about similar idea. But instead of alias this I intended to write something like this: class X : IA, IB { XIA xia; void iamethod() { xia.iamethod(); } ... }
You can also use opDispatch and __traits(getMember, ..). Don't know if it works when implementing interfaces though.
 It is not very pretty though...

 But you can also solve it with mixin templates:
 mixin template XIA {
   // all IA methods
 }
 mixin template XIB {
   // all IB methods
 }

 class X : IA, IB {
   mixin XIA!();
   mixin XIB!();
 }
This would make the code separation easy to manage, but I am concerned about debugging. How is e.g. gdb able to debug mixins? I think I have read somewhere in the D or D-learn, that the dmd can produce the file with mixed-in code for the debugger, but I am not sure how to find it. Martin
It's not string mixins: mixin template XIA() { void a() { ... } // regular function } class X : IA { mixin XIA!() } XIA is injected into X, so X now looks like class X : IA { void a() { ... } }
Mar 29 2012
parent Martin Drasar <drasar ics.muni.cz> writes:
On 29.3.2012 13:05, simendsjo wrote:
 It's not string mixins:
 mixin template XIA() {
   void a() { ... } // regular function
 }
 class X : IA {
   mixin XIA!()
 }
 
 XIA is injected into X, so X now looks like
 class X : IA {
   void a() { ... }
 }
I should have thought and experiment more before writing. Did a quick test and the gdb jumps nicely into the mixin template. So the debugging is a breeze. Thanks simendsjo for your help. I think that I know now everything I needed. Regards Martin
Mar 29 2012