www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - quirks of functions and delegates

reply Ender KaShae <astrothayne gmail.com> writes:
I have two questions concerning functions and delegates (as they are so similar
I will refer to them simply as functions from now on)  1.) can you specify a
template argument to be a function and 2.) can you have arrays of functions

1.) when I try template t(type: function) I get an error, but there must be
some way to specify that you need the type to be a function

2.) in an example in the docs it says that arrays of functions are invalid
types in c++ and d, however i've used arrays of function pointers in c++ and it
seems strange that such a type would be invalid, a function pointer is after
all just a pointer
Jul 28 2007
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ender KaShae" <astrothayne gmail.com> wrote in message 
news:f8ghug$5bg$1 digitalmars.com...

 1.) when I try template t(type: function) I get an error, but there must 
 be some way to specify that you need the type to be a function
template Templ(T : U function(V), U, V...) { } void main() { mixin Templ!(int); // fails mixin Templ!(void function(int, float)); // OK } :)
 2.) in an example in the docs it says that arrays of functions are invalid 
 types in c++ and d, however i've used arrays of function pointers in c++ 
 and it seems strange that such a type would be invalid, a function pointer 
 is after all just a pointer
There's a slight difference. A function pointer is valid in both languages, but a function type is illegal. It's very difficult to get at a function type in D, but possible. Consider: typedef void Foo(); Foo[] f; typedef void function() Bar; Bar[] g; Notice that the first defines Foo as a function -- not function _pointer_ -- type. Foo[] f; fails. But the second defines Bar as a function pointer, and Bar[] g is fine.
Jul 28 2007
prev sibling next sibling parent reply Ender KaShae <astrothayne gmail.com> writes:
Jarrett Billingsley Wrote:

 "Ender KaShae" <astrothayne gmail.com> wrote in message 
 news:f8ghug$5bg$1 digitalmars.com...
 
 1.) when I try template t(type: function) I get an error, but there must 
 be some way to specify that you need the type to be a function
template Templ(T : U function(V), U, V...) { } void main() { mixin Templ!(int); // fails mixin Templ!(void function(int, float)); // OK } :)
I tried that, however when instantiating the template the return type and paramater tuple must be explicitly given, using a static if statement can be used to the same affect however
 
 2.) in an example in the docs it says that arrays of functions are invalid 
 types in c++ and d, however i've used arrays of function pointers in c++ 
 and it seems strange that such a type would be invalid, a function pointer 
 is after all just a pointer
There's a slight difference. A function pointer is valid in both languages, but a function type is illegal. It's very difficult to get at a function type in D, but possible. Consider: typedef void Foo(); Foo[] f; typedef void function() Bar; Bar[] g; Notice that the first defines Foo as a function -- not function _pointer_ -- type. Foo[] f; fails. But the second defines Bar as a function pointer, and Bar[] g is fine.
Jul 31 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Ender,

 Jarrett Billingsley Wrote:
 
 "Ender KaShae" <astrothayne gmail.com> wrote in message
 news:f8ghug$5bg$1 digitalmars.com...
 
 1.) when I try template t(type: function) I get an error, but there
 must be some way to specify that you need the type to be a function
 
template Templ(T : U function(V), U, V...) { } void main() { mixin Templ!(int); // fails mixin Templ!(void function(int, float)); // OK } :)
I tried that, however when instantiating the template the return type and paramater tuple must be explicitly given, using a static if statement can be used to the same affect however
might this work? (I haven't tried it yet) template T(F) { staic if(is(F R == function)) else static assert(false); }
Jul 31 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <ao pathlink.com> wrote in message 
news:ce0a3343c58c8c9a19db144d622 news.digitalmars.com...
 might this work? (I haven't tried it yet)

 template T(F)
 {
   staic if(is(F R == function))
   else
     static assert(false);
 }
shorter: template T(F) { static assert(is(F == function)); }
Jul 31 2007
prev sibling next sibling parent reply Ender KaShae <astrothayne gmail.com> writes:
Jarrett Billingsley Wrote:

 "Ender KaShae" <astrothayne gmail.com> wrote in message 
 news:f8ghug$5bg$1 digitalmars.com...
 
 1.) when I try template t(type: function) I get an error, but there must 
 be some way to specify that you need the type to be a function
template Templ(T : U function(V), U, V...) { } void main() { mixin Templ!(int); // fails mixin Templ!(void function(int, float)); // OK } :)
This doesn't quite work, when only a function type is passed I get errors saying that the template was not instatiated correctly and a ton of weird errors about function pointer not implicitly casting to int's, I have no idea what that's about however when the return and paramater types are explicitly given it runs fine, though it's a little inconvienent to have to supply those twice
 
 2.) in an example in the docs it says that arrays of functions are invalid 
 types in c++ and d, however i've used arrays of function pointers in c++ 
 and it seems strange that such a type would be invalid, a function pointer 
 is after all just a pointer
There's a slight difference. A function pointer is valid in both languages, but a function type is illegal. It's very difficult to get at a function type in D, but possible. Consider: typedef void Foo(); Foo[] f; typedef void function() Bar; Bar[] g; Notice that the first defines Foo as a function -- not function _pointer_ -- type. Foo[] f; fails. But the second defines Bar as a function pointer, and Bar[] g is fine.
so what exactly does Foo mean (without the & operator) and why would anyone want a Foo[] (whatever that means) it seems to me that Foo is a symbol, not a type. on that note, if you have a function int func(); and evaluate typeid(typeof(func)) you get the type int() which is odd since func is evaluated the same as func() so the type should just be int
Aug 01 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ender KaShae" <astrothayne gmail.com> wrote in message 
news:f8qffl$er3$1 digitalmars.com...
 This doesn't quite work, when only a function type is passed I get errors 
 saying that the template was not instatiated correctly and a ton of weird 
 errors about function pointer not implicitly casting to int's, I have no 
 idea what that's about
 however when the return and paramater types are explicitly given it runs 
 fine, though it's a little inconvienent to have to supply those twice
I'm going to have to see some of your code. This works fine for me: template Templ(T : U function(V), U, V...) { const Templ = T.stringof; } void main() { pragma(msg, Templ!(int function(float))); pragma(msg, Templ!(void function(char[], int[char[]]))); }
 so what exactly does Foo mean (without the & operator) and why would 
 anyone want a Foo[] (whatever that means)  it seems to me that Foo is a 
 symbol, not a type.
Foo is a type. You can make pointers by adding an asterisk to it like any other type: Foo*. It's not a very useful type, it's just there for completeness.
 on that note, if you have a function int func(); and evaluate 
 typeid(typeof(func)) you get the type int() which is odd since func is 
 evaluated the same as func() so the type should just be int
Again, I'm going to have to see code. function int func() is an incomplete function literal. It means nothing and does not compile. However if you write "int function() func;" and then get the typeid(typeof(func)), it's "int()*" (that is a pointer to a function which takes nothing and returns an int), which makes sense because the "call a function without parens" does not apply to function _pointers_, only _functions_ (there's a use for that function type!).
Aug 01 2007
prev sibling parent reply Ender KaShae <astrothayne gmail.com> writes:
Jarrett Billingsley Wrote:


 I'm going to have to see some of your code.  This works fine for me:
 
 template Templ(T : U function(V), U, V...)
 {
     const Templ = T.stringof;
 }
 
 void main()
 {
     pragma(msg, Templ!(int function(float)));
     pragma(msg, Templ!(void function(char[], int[char[]])));
 }
for me this outputs "Error: string expected for message not Templ" this is the code that I used (and failed): template Templ(T : U function(V), U, V...) { T f; U call(V v) { return f(v);} } void func(int i, float f, char[] s) { writefln(i, f, s); } void main() { alias Templ!(void function(int, float, char[])) TemplTest; TemplTest.f = &func; TemplTest.call(1, 1.0, "1"); } the error messages were: main.d(11): Error: expected 3 arguments, not 0 main.d(20): template instance main.Templ!(void(*)(int, float, char[])) error instantiating main.d(21): Error: template instance 'Templ!(void(*)(int, float, char[]))' is not a variable main.d(21): Error: no property 'f' for type 'int' main.d(21): Error: constant (Templ!(void(*)(int, float, char[]))).f is not an lvalue main.d(21): Error: cannot implicitly convert expression (& func) of type void(*)(int, float, char[]) to int main.d(22): Error: template instance 'Templ!(void(*)(int, float, char[]))' is not a variable main.d(22): Error: no property 'call' for type 'int' main.d(22): Error: function expected before (), not 1 of type int
 
 on that note, if you have a function int func(); and evaluate 
 typeid(typeof(func)) you get the type int() which is odd since func is 
 evaluated the same as func() so the type should just be int
Again, I'm going to have to see code. function int func() is an incomplete function literal. It means nothing and does not compile. However if you write "int function() func;" and then get the typeid(typeof(func)), it's "int()*" (that is a pointer to a function which takes nothing and returns an int), which makes sense because the "call a function without parens" does not apply to function _pointers_, only _functions_ (there's a use for that function type!).
heres the code: int Foo() {return 1;} void main() { writefln(typeid(typeof(Foo))); } prints int() writefln(typeof(Foo)); gives "Error: type int() is not an expression" writefln(typeid(Foo)); gives the error: "function main.Foo is used as a type"
Aug 02 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ender KaShae" <astrothayne gmail.com> wrote in message 
news:f8t0t1$1m93$1 digitalmars.com...
 template Templ(T : U function(V), U, V...)
 {
     const Templ = T.stringof;
 }

 void main()
 {
     pragma(msg, Templ!(int function(float)));
     pragma(msg, Templ!(void function(char[], int[char[]])));
 }
for me this outputs "Error: string expected for message not Templ"
You must have an old compiler then. This works fine with DMD 1.020 and should work in 2.003 by proxy.
 this is the code that I used (and failed):
 template Templ(T : U function(V), U, V...)
 {
    T f;
    U call(V v) { return f(v);}
 }
I think you may have found a bug here. For some reason, T is correct, U is correct, but V ends up as an empty tuple every time. Odd.
 int Foo() {return 1;}

 void main() {
 writefln(typeid(typeof(Foo)));
 }

 prints int()
I see what you're saying now, and it's actually not ambiguous. See, the "function call without parens" only comes into effect when symbol lookup finds that the symbol is a function type, but the destination is a different type. Then it implicitly inserts the parens and tries to do semantic analysis on it again. However, inside typeof(), there's no ambiguity; typeof(Foo) just means "the type of the symbol Foo". However, if you do something like "writefln(typeid(typeof(Foo + 1)))" _now_ the implicit function call kicks in, and you get "int".
 writefln(typeof(Foo));

 gives "Error: type int() is not an expression"
Makes sense, you can't use a type as an expression.
 writefln(typeid(Foo));

 gives the error: "function main.Foo is used as a type"
Again makes sense, as Foo refers to a function, and not a type.
Aug 02 2007