www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: quirks of functions and delegates

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[]])));
 }

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!).

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[]])));
 }


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