Thread overview
Constant function/delegate literal
Jan 14, 2012
Vladimir Matveev
Jan 14, 2012
Andrej Mitrovic
Jan 15, 2012
Vladimir Matveev
Jan 15, 2012
H. S. Teoh
Jan 15, 2012
Timon Gehr
Jan 17, 2012
Don Clugston
Jan 17, 2012
Timon Gehr
January 14, 2012
Hi,

Is there a reason why I cannot compile the following code:

module test;

struct Test {
    int delegate(int) f;
}

Test s = Test((int x) { return x + 1; });

void main(string[] args) {
    return;
}

dmd 2.057 says:

test.d(7): Error: non-constant expression cast(int delegate(int))delegate pure
nothrow @safe int(int x)
{
return x + 1;
}

?

This is simple example; what I want to do is to create a global variable containing a structure with some ad-hoc defined functions. The compiler complains that it "cannot evaluate .... at compile time". I think this could be solved by defining a function returning needed structure, but I think this is cumbersome and inconvenient.

Best regards,
Vladimir Matveev.
January 14, 2012
I guess these are CTFE (compile-time function evaluation) issues,
someone else might know more. A workaround is to use a module
constructor which will run before main():

struct Test {
   int delegate(int) f;
}

Test s;

static this() {
    s = Test((int x) { return x + 1; });
}

Note that 's' is thread-local, to make it shared across threads but without implicit synchronization you can use:

__gshared Test s;

shared static this() {
    s = Test((int x) { return x + 1; });
}

Note the use of *shared* in the module ctor. Without 'shared' it would run every time a new thread was spawned.
January 15, 2012
Thanks, that was very helpful. Module initializer works like a charm. Shame I didn't find it in the documentation. Thanks again.

Best regards,
Vladimir.
January 15, 2012
On Sun, Jan 15, 2012 at 02:21:04PM +0000, Vladimir Matveev wrote:
> Thanks, that was very helpful. Module initializer works like a charm. Shame I didn't find it in the documentation. Thanks again.
[...]

It's discussed briefly in Andrei's book (section 11.3, p.356).


T

-- 
If it's green, it's biology, If it stinks, it's chemistry, If it has numbers it's math, If it doesn't work, it's technology.
January 15, 2012
On 01/14/2012 07:13 PM, Vladimir Matveev wrote:
> Hi,
>
> Is there a reason why I cannot compile the following code:
>
> module test;
>
> struct Test {
>      int delegate(int) f;
> }
>
> Test s = Test((int x) { return x + 1; });
>
> void main(string[] args) {
>      return;
> }
>
> dmd 2.057 says:
>
> test.d(7): Error: non-constant expression cast(int delegate(int))delegate pure
> nothrow @safe int(int x)
> {
> return x + 1;
> }
>
> ?
>
> This is simple example; what I want to do is to create a global variable
> containing a structure with some ad-hoc defined functions. The compiler
> complains that it "cannot evaluate .... at compile time". I think this could
> be solved by defining a function returning needed structure, but I think this
> is cumbersome and inconvenient.
>
> Best regards,
> Vladimir Matveev.

I think it should work. I have filed a bug report:
http://d.puremagic.com/issues/show_bug.cgi?id=7298


January 17, 2012
On 15/01/12 20:35, Timon Gehr wrote:
> On 01/14/2012 07:13 PM, Vladimir Matveev wrote:
>> Hi,
>>
>> Is there a reason why I cannot compile the following code:
>>
>> module test;
>>
>> struct Test {
>> int delegate(int) f;
>> }
>>
>> Test s = Test((int x) { return x + 1; });
>>
>> void main(string[] args) {
>> return;
>> }
>>
>> dmd 2.057 says:
>>
>> test.d(7): Error: non-constant expression cast(int
>> delegate(int))delegate pure
>> nothrow @safe int(int x)
>> {
>> return x + 1;
>> }
>>
>> ?

The 'this' pointer in the delegate:
Test((int x) { return x + 1; });

is a pointer to the struct literal, which isn't constant. You actually want it to point to variable s.

OTOH if it were a function, it should work, but it currently doesn't.

>>
>> This is simple example; what I want to do is to create a global variable
>> containing a structure with some ad-hoc defined functions. The compiler
>> complains that it "cannot evaluate .... at compile time". I think this
>> could
>> be solved by defining a function returning needed structure, but I
>> think this
>> is cumbersome and inconvenient.
>>
>> Best regards,
>> Vladimir Matveev.
>
> I think it should work. I have filed a bug report:
> http://d.puremagic.com/issues/show_bug.cgi?id=7298
>
>

January 17, 2012
On 01/17/2012 05:02 PM, Don Clugston wrote:
> On 15/01/12 20:35, Timon Gehr wrote:
>> On 01/14/2012 07:13 PM, Vladimir Matveev wrote:
>>> Hi,
>>>
>>> Is there a reason why I cannot compile the following code:
>>>
>>> module test;
>>>
>>> struct Test {
>>> int delegate(int) f;
>>> }
>>>
>>> Test s = Test((int x) { return x + 1; });
>>>
>>> void main(string[] args) {
>>> return;
>>> }
>>>
>>> dmd 2.057 says:
>>>
>>> test.d(7): Error: non-constant expression cast(int
>>> delegate(int))delegate pure
>>> nothrow @safe int(int x)
>>> {
>>> return x + 1;
>>> }
>>>
>>> ?
>
> The 'this' pointer in the delegate:
> Test((int x) { return x + 1; });
>
> is a pointer to the struct literal, which isn't constant.
> You actually want it to point to variable s.


The struct literal residing in static storage has a variable address?
Why would the context pointer point to the struct literal anyway? It is not required.

>
> OTOH if it were a function, it should work, but it currently doesn't.
>

It should even work for delegates. The context pointer would just be null.