www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Defining member fuctions of a class or struct out side of the

reply Jamal <jamalsmith95.bc gmail.com> writes:
Warning D newb here.

Is it possible to define a member function outside of the 
class/struct like in C++;

class x { body
     void foo(int* i);
};

void x::foo(int* i){
     *i++;
}

Or is it just D-like to define everything inside the class/struct 
body?
May 13 2016
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/13/16 2:41 PM, Jamal wrote:
 Warning D newb here.

 Is it possible to define a member function outside of the class/struct
 like in C++;
Not within the same file. You can have an "interface file", extension .di, which hides the bodies of functions. But inside the implementation file, you must repeat the class/struct definition. So it's a lot of extra work. The compiler can spit out a .di file based on your implementation with the bodies hidden, but it's not perfect. You also can't hide template function bodies. What is your use case, or is it just that you prefer doing it that way? -Steve
May 13 2016
prev sibling next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 05/13/2016 11:41 AM, Jamal wrote:
 Warning D newb here.

 Is it possible to define a member function outside of the class/struct
 like in C++;

 class x { body
      void foo(int* i);
 };

 void x::foo(int* i){
      *i++;
 }

 Or is it just D-like to define everything inside the class/struct body?
Also check out the feature called UFCS. It is not the exact answer to your question but it may be more applicable in some designs. Ali
May 13 2016
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2016-05-13 20:41, Jamal wrote:

 Or is it just D-like to define everything inside the class/struct body?
Yes, the D-way is to define everything directly inside the class/struct. -- /Jacob Carlborg
May 14 2016
prev sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, May 13, 2016 18:41:16 Jamal via Digitalmars-d-learn wrote:
 Warning D newb here.

 Is it possible to define a member function outside of the
 class/struct like in C++;

 class x { body
      void foo(int* i);
 };

 void x::foo(int* i){
      *i++;
 }

 Or is it just D-like to define everything inside the class/struct
 body?
The language is designed with the idea that you're going to define all of the functions inline and not have prototypes. So, if you're trying to do it differently, you're going to have a lot of problems. That being said, you have two options: 1. Write a D interface file. Its extension is .di, and it's intended to be similar to a C/C++ header file for the purpose of hiding implementation when distributing a library without the source code. However, you still need to write the .d file exactly like you would normally. The .di file is just for other folks that you don't want to give the source to. So, it generates a lot more work for you with arguably no benefit if you're just looking to separate interface and implementation. And any templated types and auto-return functions will still have to have their full source in the .di file, and any functions that you want to be inlined will need their source in the .di file. So, a lot of stuff is likely going to need to be in the .di file anyway (especially in range-based code, since that tends to be _very_ template-heavy). To save effort in generating a .di file, you can use the compiler to generate one for you (I think that the flags that start with -H are for that), but last I heard, it's pretty conservative in removing stuff, so a lot of the implementation is going to be left in there even if it doesn't need to be. So, you're likely going to have to edit it manually. I think that the general consensus in the D community has been that .di files really aren't worth it. If you _need_ them, because you want to keep your source hidden, then they're what you need, but they're a pain otherwise. 2. You can use UFCS (Universal Function Call Syntax). Ali's book talks about it here: http://ddili.org/ders/d.en/ufcs.html but basically what it comes down to is that you call call a free function as if it were a member function of its first argument. e.g. auto foo(MyClass m, int i) {..} auto result = myClass.foo(42); This allows you to essentially add member functions without them having to be member functions. You don't end up with prototypes or with them being listed as member functions in your struct or class, but the functions are then separate from the struct or class, and you don't need their implementation inside the struct or class. Where UFCS is truly useful though is it allows generic code to call functions without caring whether they're member functions or free functions. For instance, if you use std.algorith.find with UFCS inside of a templated function, and you call it with UFCS, and the type that you call it on has a member function called find which is more efficient for it than the generic find would be, then the member function will be called, whereas for all of those types that don't define find, the generic one will work just fine. So, your code doesn't have to care whether the function is actually a member function or not. But a lot of folks like to use UFCS just because it allows them to chain functions left-to-right rather than using the classical, functional style with parens, which chains right-to-left and ends up with a lot of parens. e.g. auto arr = [1, 7, 19, 42, 9]; auto result = arr.filter!(a => a < 20)().map!(a => to!string(a))().array(); assert(result == ["1", "7", "19", "9"]); or auto arr = [1, 7, 19, 42, 9]; auto result = arr.filter!(a => a < 20)() .map!(a => to!string(a))() .array(); assert(result == ["1", "7", "19", "9"]); instead of auto arr = [1, 7, 19, 42, 9]; auto result = array(map!(a => to!string(a))(filter!(a => a < 20)(arr))); assert(result == ["1", "7", "19", "9"]); In any case, D is set up so that you don't normally separate declarations and definitons like you would in C/C++, and its compilation model is _far_ more efficient than C/C++, so it's not really necessary to do it in quite the same way that it is in C/C++. It is occasionally annoying when you just want to see which member functions and member functions are declared on a type, but you get used to it, and you can always generate documentation to if you just want to see the declarations. We're in basically the same boat as Java with this sort of thing. - Jonathan M Davis
May 14 2016