digitalmars.D - Function prototype + definition in the same file
- Manu (63/63) Sep 25 2012 So I have this recurring pattern, it's really starting to annoy me.
- bearophile (6/10) Sep 25 2012 Maybe there are better ways to solve your problems (even changing
- Manu (4/12) Sep 25 2012 Can you suggest a more direct approach? Declaring prototypes seems
- Steven Schveighoffer (4/18) Sep 25 2012 This compiles. Do you have a better case to show the problem?
- Manu (19/40) Sep 25 2012 void blah();
- Steven Schveighoffer (50/95) Sep 25 2012 Oh, that is funny. I simply compiled the functions and didn't call them...
- Jacob Carlborg (6/11) Sep 25 2012 I guess you already figured this out but a single mixin with a lot of
- deadalnix (5/68) Sep 25 2012 This is code duplication and is generally considered as a bad practice.
- Maxim Fomin (6/10) Sep 25 2012 This is neither a code duplication (there is certain distinction
- deadalnix (3/13) Sep 25 2012 This is code duplication. And this has been considered a problem in
- Steven Schveighoffer (12/26) Sep 25 2012 een
- Jonathan M Davis (15/39) Sep 25 2012 It's still code duplication, because you've now listed the function sign...
-
Steven Schveighoffer
(35/75)
Sep 25 2012
On Tue, 25 Sep 2012 16:07:51 -0400, Jonathan M Davis
- deadalnix (3/9) Sep 26 2012 This is why I suggested to improve the di generator instead of allowing
- Jacob Carlborg (5/7) Sep 25 2012 They're necessary for linking with C functions. But except from that I
- Jesse Phillips (20/27) Sep 25 2012 I'm not sure I understand what benefit you are giving, I'll
- Timon Gehr (4/20) Sep 25 2012 It is illegal because nobody has written code to support it. It
- Timon Gehr (14/37) Sep 25 2012 (The implementation faces some challenges, the following is easy to get
- Manu (7/48) Sep 26 2012 I'm not sure I understand the point being illustrated here. I don't see ...
- deadalnix (5/50) Sep 26 2012 From a compiler perspective, the example above is hell. That was his po...
- Manu (8/74) Sep 26 2012 I can't imagine why the example above is hell, but I know nothing about ...
- Jacob Carlborg (4/10) Sep 26 2012 If the definition is found first, just ignore the prototype?
- Manu (2/12) Sep 26 2012 Indeed.
- Maxim Fomin (3/6) Sep 26 2012 It seems to be just opposite: creating ambiguity between function
- Rainer Schuetze (19/27) Sep 26 2012 [...]
- Manu (4/19) Sep 27 2012 Good idea! I'll give that a shot.
So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff } I really need this. Why is it illegal? Is there chance of having this supported? What are the problems? My problem is essentially to do with supporting both static or dynamic linkage optionally, but it also shows up in situations where I want to perform comprehensive magic code generation, but want clear-readable user declarations. The simplest case: I have an extern that I may want to statically or dynamically link. In the case of static linkage, one just produces a prototype, and it links, no problem. In the case of dynamic linkage, one must produce a stub for the function, a function pointer to call through, and perhaps some code to hook-up the function pointer at init. I have a fairly comprehensive binding solution which automates the work in the case of dynamic linkage, but the problem is the way the user defines the functions that exist in the D code. I'd like it if the users would just write the prototypes, they'd be easily readable, simple to create by cutting and pasting straight from C code. And when statically linking, it would just work, the module hook-up mixin does nothing in this configuration. In the case of dynamic linkage, a single hook-up mixin in the file somewhere could scan the module for these prototypes and generate the stubs, function pointers, and the boot-up code that would connect them (while validating their signatures against the extern import table, etc). This approach isn't supported though. What I do instead: mixin( ImportFunction!( "functionName", int function( int arg1, float arg2, ref in SomeStruct arg3 ), "pure nothrow" ) ); mixin( ImportFunction!( "functionName2", int function() ) ); mixin( ImportFunction!( "functionName3", int function( int x, int y ), "nothrow" ) ); etc etc These templates produce, from the information provided, either a prototype for static linkage, or the { stub, func pointer, initialisation info } for dynamic linkage. I really don't like doing it this way for a number of reasons: *** This results in hundreds of mixins, which quickly lead to intolerable compile times (to the point where D is losing it's appeal as a viable choice for our needs). If done my preferred way, I could do the magic with a single mixin at the bottom of the file. * It's barely readable. * Much more annoying to write and maintain when the counterpart API changes, and is more error-prone. * IDE features don't work properly; syntax highlighting, hover info, go-to-definition, etc. I also have numerous more advanced cases of the same problem, and becomes even more unsightly when used in structs to emulate dynamic linkage to static methods of C++ classes. The solution is seemingly trivial; allow function prototypes and definitions to exist in the same file, like in C/C++. Go on, tear me apart... :)
Sep 25 2012
Manu:I have a fairly comprehensive binding solution which automates the work in the case of dynamic linkage, but the problem is the way the user defines the functions that exist in the D code.Maybe there are better ways to solve your problems (even changing D language in some ways), and keep avoiding the need of free floating ghosts of functions. Bye, bearophile
Sep 25 2012
On 25 September 2012 15:21, bearophile <bearophileHUGS lycos.com> wrote:Manu: I have a fairly comprehensive binding solution which automates the work inCan you suggest a more direct approach? Declaring prototypes seems completely natural, supports all the expected IDE features, and in the simple/common case (static linkage) requires absolutely no magic voodoo.the case of dynamic linkage, but the problem is the way the user defines the functions that exist in the D code.Maybe there are better ways to solve your problems (even changing D language in some ways), and keep avoiding the need of free floating ghosts of functions.
Sep 25 2012
On Tue, 25 Sep 2012 07:53:17 -0400, Manu <turkeyman gmail.com> wrote:So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++)Doing this is not illegal.Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff }This compiles. Do you have a better case to show the problem? -Steve
Sep 25 2012
On 25 September 2012 17:25, Steven Schveighoffer <schveiguy yahoo.com>wrote:On Tue, 25 Sep 2012 07:53:17 -0400, Manu <turkeyman gmail.com> wrote: So I have this recurring pattern, it's really starting to annoy me.void blah(); void blah() { int x = 0; } void f() { blah(); // <- call it } W:\project\main\sourcedata\plugins\remedy\modules\test_module.d(38):Error: function remedy.testmodule.blah called with argument types: (()) matches both: remedy.testmodule.blah() and: remedy.testmodule.blah() Obviously, one is just a prototype, and the symbol is resolved within the local file.It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++)Doing this is not illegal. Eg,void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff }This compiles. Do you have a better case to show the problem?
Sep 25 2012
On Tue, 25 Sep 2012 10:40:41 -0400, Manu <turkeyman gmail.com> wrote:On 25 September 2012 17:25, Steven Schveighoffer <schveiguy yahoo.com>wrote:Oh, that is funny. I simply compiled the functions and didn't call them, assuming if that compiled it was legal. This is definitely a bug. In fact you can implement a function *twice* and this isn't an error. Check this out: testme2.d: module testme2; import std.stdio; void foo() { writeln("first"); } void foo() { writeln("second"); } testme2.di: module testme2; void foo(); testme.d: import testme2; void main() { foo(); } Compile like this: dmd -c testme2.d dmd testme.d testme2.o links, and when I run, it displays: first So clearly there isn't something right here, that should definitely be an error. I think there are two errors here. First, the spec does not say you cannot prototype a function before declaring it. All it says is: Functions without bodies: int foo(); that are not declared as abstract are expected to have their implementations elsewhere, and that implementation will be provided at the link step. This enables an implementation of a function to be completely hidden from the user of it, and the implementation may be in another language such as C, assembler, etc. from: http://dlang.org/function.html I don't see any rules that would preclude pre-declaring a prototype, even if it's not promoted to do this (after all, forward references should always work, right?). Second, you should not be able to compile two identically prototyped functions with bodies into an object file, I have no idea how that even works. -SteveOn Tue, 25 Sep 2012 07:53:17 -0400, Manu <turkeyman gmail.com> wrote: So I have this recurring pattern, it's really starting to annoy me.void blah(); void blah() { int x = 0; } void f() { blah(); // <- call it } W:\project\main\sourcedata\plugins\remedy\modules\test_module.d(38):Error: function remedy.testmodule.blah called with argument types: (()) matches both: remedy.testmodule.blah() and: remedy.testmodule.blah()It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++)Doing this is not illegal. Eg,void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff }This compiles. Do you have a better case to show the problem?
Sep 25 2012
On 2012-09-25 13:53, Manu wrote:I really don't like doing it this way for a number of reasons: *** This results in hundreds of mixins, which quickly lead to intolerable compile times (to the point where D is losing it's appeal as a viable choice for our needs). If done my preferred way, I could do the magic with a single mixin at the bottom of the file.I guess you already figured this out but a single mixin with a lot of code is a lot faster than several mixins with little code. Although this will decrease the readability even further. -- /Jacob Carlborg
Sep 25 2012
Le 25/09/2012 13:53, Manu a écrit :So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff } I really need this. Why is it illegal? Is there chance of having this supported? What are the problems? My problem is essentially to do with supporting both static or dynamic linkage optionally, but it also shows up in situations where I want to perform comprehensive magic code generation, but want clear-readable user declarations. The simplest case: I have an extern that I may want to statically or dynamically link. In the case of static linkage, one just produces a prototype, and it links, no problem. In the case of dynamic linkage, one must produce a stub for the function, a function pointer to call through, and perhaps some code to hook-up the function pointer at init. I have a fairly comprehensive binding solution which automates the work in the case of dynamic linkage, but the problem is the way the user defines the functions that exist in the D code. I'd like it if the users would just write the prototypes, they'd be easily readable, simple to create by cutting and pasting straight from C code. And when statically linking, it would just work, the module hook-up mixin does nothing in this configuration. In the case of dynamic linkage, a single hook-up mixin in the file somewhere could scan the module for these prototypes and generate the stubs, function pointers, and the boot-up code that would connect them (while validating their signatures against the extern import table, etc). This approach isn't supported though. What I do instead: mixin( ImportFunction!( "functionName", int function( int arg1, float arg2, ref in SomeStruct arg3 ), "pure nothrow" ) ); mixin( ImportFunction!( "functionName2", int function() ) ); mixin( ImportFunction!( "functionName3", int function( int x, int y ), "nothrow" ) ); etc etc These templates produce, from the information provided, either a prototype for static linkage, or the { stub, func pointer, initialisation info } for dynamic linkage. I really don't like doing it this way for a number of reasons: *** This results in hundreds of mixins, which quickly lead to intolerable compile times (to the point where D is losing it's appeal as a viable choice for our needs). If done my preferred way, I could do the magic with a single mixin at the bottom of the file. * It's barely readable. * Much more annoying to write and maintain when the counterpart API changes, and is more error-prone. * IDE features don't work properly; syntax highlighting, hover info, go-to-definition, etc. I also have numerous more advanced cases of the same problem, and becomes even more unsightly when used in structs to emulate dynamic linkage to static methods of C++ classes. The solution is seemingly trivial; allow function prototypes and definitions to exist in the same file, like in C/C++. Go on, tear me apart... :)This is code duplication and is generally considered as a bad practice. I'm not convinced that the language should be modified to allow something that is known as bad practice. What you need here is a more robust di generator IMO.
Sep 25 2012
On Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:This is code duplication and is generally considered as a bad practice. I'm not convinced that the language should be modified to allow something that is known as bad practice. What you need here is a more robust di generator IMO.This is neither a code duplication (there is certain distinction between prototype and body) nor a bad practice - this is a common pattern in C and C++. It is surprising that D cannot do such a simple thing which in addition is not harmless, so there is no sense in depreciating it.
Sep 25 2012
Le 25/09/2012 20:57, Maxim Fomin a écrit :On Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:This is code duplication. And this has been considered a problem in C/C++ for a while now.This is code duplication and is generally considered as a bad practice. I'm not convinced that the language should be modified to allow something that is known as bad practice. What you need here is a more robust di generator IMO.This is neither a code duplication (there is certain distinction between prototype and body) nor a bad practice - this is a common pattern in C and C++. It is surprising that D cannot do such a simple thing which in addition is not harmless, so there is no sense in depreciating it.
Sep 25 2012
On Tue, 25 Sep 2012 15:23:50 -0400, deadalnix <deadalnix gmail.com> wrot= e:Le 25/09/2012 20:57, Maxim Fomin a =C3=A9crit :eenOn Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:This is code duplication and is generally considered as a bad practice. I'm not convinced that the language should be modified to allow something that is known as bad practice. What you need here is a more robust di generator IMO.This is neither a code duplication (there is certain distinction betw=Cprototype and body) nor a bad practice - this is a common pattern in =inand C++. It is surprising that D cannot do such a simple thing which =addition is not harmless, so there is no sense in depreciating it.This is code duplication. And this has been considered a problem in =C/C++ for a while now.No, it's a prototype. Note that it's *required* if you want to hide implementation using .di = files. There is no code involved, it's just generating a symbol reference in th= e = object file. -Steve
Sep 25 2012
On Tuesday, September 25, 2012 15:48:11 Steven Schveighoffer wrote:On Tue, 25 Sep 2012 15:23:50 -0400, deadalnix <deadalnix gmail.com> wrote:It's still code duplication, because you've now listed the function signature twice. Yes, it's minimal code duplication, but it's still duplicating code. It's necessary for stuff like .di files (which are code duplication by definition, because they're duplicating a module - or at least part of it), but most everyone I know has thought (where it's come anyway) that prototypes were a _bad_ thing about C/C++. So, eliminating them as much as possible would generally be good, and even when it comes to .di files, given their limitations (e.g. disabling inlining and CTFE), we arguably should have a better solution for interface files anyway (e.g. having a binary file with the partially compiled code and generated documentation alongside it giving the API), in which case we wouldn't even need prototypes for interface files anymore. If anything, I'd argue that the fact that prototypes are part of the language is a sign of a deficiency in the language (especially if they're necessary). - Jonathan M DavisLe 25/09/2012 20:57, Maxim Fomin a écrit :No, it's a prototype. Note that it's *required* if you want to hide implementation using .di files. There is no code involved, it's just generating a symbol reference in the object file.On Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:This is code duplication. And this has been considered a problem in C/C++ for a while now.This is code duplication and is generally considered as a bad practice. I'm not convinced that the language should be modified to allow something that is known as bad practice. What you need here is a more robust di generator IMO.This is neither a code duplication (there is certain distinction between prototype and body) nor a bad practice - this is a common pattern in C and C++. It is surprising that D cannot do such a simple thing which in addition is not harmless, so there is no sense in depreciating it.
Sep 25 2012
On Tue, 25 Sep 2012 16:07:51 -0400, Jonathan M Davis <jmdavisProg gmx.co= m> = wrote:On Tuesday, September 25, 2012 15:48:11 Steven Schveighoffer wrote:On Tue, 25 Sep 2012 15:23:50 -0400, deadalnix <deadalnix gmail.com> =towrote:Le 25/09/2012 20:57, Maxim Fomin a =C3=A9crit :On Tuesday, 25 September 2012 at 17:48:46 UTC, deadalnix wrote:This is code duplication and is generally considered as a bad practice. I'm not convinced that the language should be modified =allow something that is known as bad practice. What you need here is a more robust di generator IMO.This is neither a code duplication (there is certain distinction =in =betweenprototype and body) nor a bad practice - this is a common pattern =ch =Cand C++. It is surprising that D cannot do such a simple thing whi=inaddition is not harmless, so there is no sense in depreciating it.=This is code duplication. And this has been considered a problem in=iC/C++ for a while now.No, it's a prototype. Note that it's *required* if you want to hide implementation using .d==files. There is no code involved, it's just generating a symbol reference in=the object file.It's still code duplication, because you've now listed the function =signature twice. Yes, it's minimal code duplication, but it's still duplicating ==code.I misunderstood, I was thinking in terms of generated code. But in any case, it's still not duplicated code. What you are doing is = = defining an interface, then attaching the implementation of the interfac= e = to the declaration by repeating its name. Would you say repeating the function signature of an interface in an = implementing class is code duplication? Would you say that typing the = name of a variable that you already declared so you could access it is = code duplication? Duplicated or not, it's still valid under the spec as far as I can tell.=It's necessary for stuff like .di files (which are code duplication by=definition, because they're duplicating a module - or at least part of==it), but most everyone I know has thought (where it's come anyway) that =prototypes were a _bad_ thing about C/C++.The main reason for having prototypes in C/C++ was so you could declare = a = symbol that you weren't defining yet. In some cases, this was necessary, because C/C++ does not have forward = references. So there is indeed very little reason in D to declare a = function, then implement it in the same file. But I think what Manu is trying to do is not exactly just "repeat the = signature", he is using the signature of the original to generate the = signature of the auto-generated function. Essentially, it's not = duplicated code on either the source or the compiled level, so disabling= = the ability to declare a function and then implement it later would = prevent this possibility. I don't think it makes sense to do that. -Steve
Sep 25 2012
Le 25/09/2012 22:43, Steven Schveighoffer a écrit :But I think what Manu is trying to do is not exactly just "repeat the signature", he is using the signature of the original to generate the signature of the auto-generated function. Essentially, it's not duplicated code on either the source or the compiled level, so disabling the ability to declare a function and then implement it later would prevent this possibility. I don't think it makes sense to do that.This is why I suggested to improve the di generator instead of allowing that in the language in a first place.
Sep 26 2012
On 2012-09-25 22:07, Jonathan M Davis wrote:I'd argue that the fact that prototypes are part of the language is a sign of a deficiency in the language (especially if they're necessary).They're necessary for linking with C functions. But except from that I agree with you. -- /Jacob Carlborg
Sep 25 2012
On Tuesday, 25 September 2012 at 11:52:38 UTC, Manu wrote:So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) [...] Go on, tear me apart... :)I'm not sure I understand what benefit you are giving, I'll explain a situation I went through. tldr: I like having a clean "header" file for static linking. It would be nice to build off that to dynamically link. I wanted to load up a DLL (C++ with C interface). Found this nifty file on stackoverflow http://stackoverflow.com/questions/3818229/loading-plugins-dlls-on-the-fly Didn't want to write all those mixins myself. I already had the "header" file for my DLL and didn't want to write all those mixins. I created an array with all the function names, then created a function which took iterated this array and asked for the function type as I'd imported the "header." I ran into a bunch of runtime errors with this setup, probably didn't like the duplication of function names. Or something completely different. Finally I went to static linking. Since I had a nice clean header I didn't need to do anything fancy, pragma(lib) my .lib file and disable the defFunctions mixin.
Sep 25 2012
On 09/25/2012 01:53 PM, Manu wrote:So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff } I really need this. Why is it illegal? Is there chance of having this supported? What are the problems? ...It is illegal because nobody has written code to support it. It should be possible to support it. I don't think there are any problems with the concept.
Sep 25 2012
On 09/26/2012 01:29 AM, Timon Gehr wrote:On 09/25/2012 01:53 PM, Manu wrote:(The implementation faces some challenges, the following is easy to get wrong: module module_; void foo(); alias foo alias1; static if(is(typeof(alias1))){ void foo(){} alias foo alias2; } static assert(__traits(isSame, alias1, alias2)); static assert(__traits(allMembers, module_).length == 3); // 2 alias, 1 function definition )So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff } I really need this. Why is it illegal? Is there chance of having this supported? What are the problems? ...It is illegal because nobody has written code to support it. It should be possible to support it. I don't think there are any problems with the concept.
Sep 25 2012
On 26 September 2012 02:35, Timon Gehr <timon.gehr gmx.ch> wrote:On 09/26/2012 01:29 AM, Timon Gehr wrote:I'm not sure I understand the point being illustrated here. I don't see how the aliases are relevant? Is an alias to a prototype somehow different than an alias to a definition? Shouldn't the discovery of a function definition within the same file as a pre-declared prototype just promote the prototype to a full definition? They are the same symbol, just that one instance adds the definition.On 09/25/2012 01:53 PM, Manu wrote:(The implementation faces some challenges, the following is easy to get wrong: module module_; void foo(); alias foo alias1; static if(is(typeof(alias1))){ void foo(){} alias foo alias2; } static assert(__traits(isSame, alias1, alias2)); static assert(__traits(allMembers, module_).length == 3); // 2 alias, 1 function definition )So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff } I really need this. Why is it illegal? Is there chance of having this supported? What are the problems? ...It is illegal because nobody has written code to support it. It should be possible to support it. I don't think there are any problems with the concept.
Sep 26 2012
Le 26/09/2012 10:14, Manu a écrit :On 26 September 2012 02:35, Timon Gehr <timon.gehr gmx.ch <mailto:timon.gehr gmx.ch>> wrote: On 09/26/2012 01:29 AM, Timon Gehr wrote: On 09/25/2012 01:53 PM, Manu wrote: So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff } I really need this. Why is it illegal? Is there chance of having this supported? What are the problems? ... It is illegal because nobody has written code to support it. It should be possible to support it. I don't think there are any problems with the concept. (The implementation faces some challenges, the following is easy to get wrong: module module_; void foo(); alias foo alias1; static if(is(typeof(alias1))){ void foo(){} alias foo alias2; } static assert(__traits(isSame, alias1, alias2)); static assert(__traits(allMembers, module_).length == 3); // 2 alias, 1 function definition ) I'm not sure I understand the point being illustrated here. I don't see how the aliases are relevant?From a compiler perspective, the example above is hell. That was his point. In other terms, supporting such a feature add complexity to the compiler, and it should come with a sufficient benefice to make sense to implement.
Sep 26 2012
On 26 September 2012 13:09, deadalnix <deadalnix gmail.com> wrote:Le 26/09/2012 10:14, Manu a =C3=A9crit :t.On 26 September 2012 02:35, Timon Gehr <timon.gehr gmx.ch <mailto:timon.gehr gmx.ch>> wrote: On 09/26/2012 01:29 AM, Timon Gehr wrote: On 09/25/2012 01:53 PM, Manu wrote: So I have this recurring pattern, it's really starting to annoy me. It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg, void func(int x); // <-- declaration of function, informs type and associated names, args, ... //later void func(int x) // <-- may be generated with magic (and may use the prototype declaration for type information as declared by the prototype above) { ... do stuff } I really need this. Why is it illegal? Is there chance of having this supported? What are the problems? ... It is illegal because nobody has written code to support it. It should be possible to support it. I don't think there are any problems with the concept. (The implementation faces some challenges, the following is easy to get wrong: module module_; void foo(); alias foo alias1; static if(is(typeof(alias1))){ void foo(){} alias foo alias2; } static assert(__traits(isSame, alias1, alias2)); static assert(__traits(allMembers, module_).length =3D=3D 3); // 2 alias, 1 function definition ) I'm not sure I understand the point being illustrated here. I don't see how the aliases are relevant?From a compiler perspective, the example above is hell. That was his poin=In other terms, supporting such a feature add complexity to the compiler, and it should come with a sufficient benefice to make sense to implement.I can't imagine why the example above is hell, but I know nothing about the compiler. I have no idea how the existing bug was implemented, but it needs to be fixed one way or another. It sounds fairly trivial to me to promote a prototype to a definition if a definition is found later in the same module.
Sep 26 2012
On 2012-09-26 12:19, Manu wrote:I can't imagine why the example above is hell, but I know nothing about the compiler. I have no idea how the existing bug was implemented, but it needs to be fixed one way or another. It sounds fairly trivial to me to promote a prototype to a definition if a definition is found later in the same module.If the definition is found first, just ignore the prototype? -- /Jacob Carlborg
Sep 26 2012
On 26 September 2012 14:21, Jacob Carlborg <doob me.com> wrote:On 2012-09-26 12:19, Manu wrote: I can't imagine why the example above is hell, but I know nothing aboutIndeed.the compiler. I have no idea how the existing bug was implemented, but it needs to be fixed one way or another. It sounds fairly trivial to me to promote a prototype to a definition if a definition is found later in the same module.If the definition is found first, just ignore the prototype?
Sep 26 2012
On Wednesday, 26 September 2012 at 10:09:14 UTC, deadalnix wrote:In other terms, supporting such a feature add complexity to the compiler, and it should come with a sufficient benefice to make sense to implement.It seems to be just opposite: creating ambiguity between function body and its declaration is a language complexity.
Sep 26 2012
On 25.09.2012 13:53, Manu wrote:> So I have this recurring pattern, it's really starting to annoy me.It stems from the fact that a function prototype and the definition can not appear in the same file in D (as it can in C/C++) Eg,[...]I also have numerous more advanced cases of the same problem, and becomes even more unsightly when used in structs to emulate dynamic linkage to static methods of C++ classes. The solution is seemingly trivial; allow function prototypes and definitions to exist in the same file, like in C/C++.I think this should be allowed, aswell as implementing forward declared enums and structs (IIRC the compiler even has some error messages that suggest that it is intended). As a workaround, you could put your prototypes into a struct and generate the declarations for the static linking and the stubs for dynamic linking from their declarations and run your magic on the members of "prototypes": struct prototypes { void fun1(int a, int b); void fun2(int a, int b); } mixin(magic([__traits(allMembers, prototypes)]) That way you don't put the symbols into the same scope as the prototypes, and you will not add new symbols to the same scope that you are iterating over.
Sep 26 2012
On 26 September 2012 20:28, Rainer Schuetze <r.sagitario gmx.de> wrote:I think this should be allowed, aswell as implementing forward declared enums and structs (IIRC the compiler even has some error messages that suggest that it is intended). As a workaround, you could put your prototypes into a struct and generate the declarations for the static linking and the stubs for dynamic linking from their declarations and run your magic on the members of "prototypes": struct prototypes { void fun1(int a, int b); void fun2(int a, int b); } mixin(magic([__traits(**allMembers, prototypes)]) That way you don't put the symbols into the same scope as the prototypes, and you will not add new symbols to the same scope that you are iterating over.Good idea! I'll give that a shot. So it seems like there is fairly general consensus on this then, is there a next step? Should I log a bug? (I think I did log one months ago)
Sep 27 2012