Thread overview
static assert / static if
Feb 23, 2007
Lionello Lunesu
Feb 23, 2007
Don Clugston
Feb 23, 2007
Lionello Lunesu
Feb 23, 2007
Lionello Lunesu
February 23, 2007
I'm confused:

template factorial(int n)
{
	static assert(n>0);
	static if (n == 1)
		const factorial = 1;
	else
		const factorial =
			n * factorial!(n-1);
}

int main()
{
	return factorial!(0);
}

The static assert doesn't trip. If I remove the recursion, it works fine, but with it the compiler stops with:

ct.d(8): template instance ct.factorial!(-3078) recursive expansion

At first I thought that the template is instantiated before the assert is tested, but the static if IS tested before recursion, so why isn't the assert? Is it a bug?

L.
February 23, 2007
Lionello Lunesu wrote:
> I'm confused:
> 
> template factorial(int n)
> {
>     static assert(n>0);
>     static if (n == 1)
>         const factorial = 1;
>     else
>         const factorial =
>             n * factorial!(n-1);
> }
> 
> int main()
> {
>     return factorial!(0);
> }
> 
> The static assert doesn't trip. If I remove the recursion, it works fine, but with it the compiler stops with:
> 
> ct.d(8): template instance ct.factorial!(-3078) recursive expansion
> 
> At first I thought that the template is instantiated before the assert is tested, but the static if IS tested before recursion, so why isn't the assert? Is it a bug?
> 
> L.

Yeah, there's something wrong with static assert. I think it does constant folding with the wrong context (many examples in bugzilla). It did work as you'd expect back around DMD 0.140, but lots of other things were broken. Inside a template, I've only got good use out of it by:

static if (n<=0) {
  static assert(0, "factorial must be >=0");
}

Actually factorial!(0) should return 1, but I'm guessing you really don't care <g>.
February 23, 2007
Don Clugston wrote:
> Lionello Lunesu wrote:
>> I'm confused:
>>
>> template factorial(int n)
>> {
>>     static assert(n>0);
>>     static if (n == 1)
>>         const factorial = 1;
>>     else
>>         const factorial =
>>             n * factorial!(n-1);
>> }
>>
>> int main()
>> {
>>     return factorial!(0);
>> }
>>
>> The static assert doesn't trip. If I remove the recursion, it works fine, but with it the compiler stops with:
>>
>> ct.d(8): template instance ct.factorial!(-3078) recursive expansion
>>
>> At first I thought that the template is instantiated before the assert is tested, but the static if IS tested before recursion, so why isn't the assert? Is it a bug?
>>
>> L.
> 
> Yeah, there's something wrong with static assert. I think it does constant folding with the wrong context (many examples in bugzilla). It did work as you'd expect back around DMD 0.140, but lots of other things were broken. Inside a template, I've only got good use out of it by:
> 
> static if (n<=0) {
>   static assert(0, "factorial must be >=0");
> }

I've searched bugzilla, but I can't seem to find this exact issue. What issues are similar to this one?

> Actually factorial!(0) should return 1, but I'm guessing you really don't care <g>.

Indeed :) but I got the code from Walter's NWCPP presentation. I guess it should static-if on n==0 instead, and uint for that matter.

L.
February 23, 2007
Don Clugston wrote:
> Lionello Lunesu wrote:
>> I'm confused:
>>
>> template factorial(int n)
>> {
>>     static assert(n>0);
>>     static if (n == 1)
>>         const factorial = 1;
>>     else
>>         const factorial =
>>             n * factorial!(n-1);
>> }
>>
>> int main()
>> {
>>     return factorial!(0);
>> }
>>
>> The static assert doesn't trip. If I remove the recursion, it works fine, but with it the compiler stops with:
>>
>> ct.d(8): template instance ct.factorial!(-3078) recursive expansion
>>
>> At first I thought that the template is instantiated before the assert is tested, but the static if IS tested before recursion, so why isn't the assert? Is it a bug?
>>
>> L.
> 
> Yeah, there's something wrong with static assert. I think it does constant folding with the wrong context (many examples in bugzilla). It did work as you'd expect back around DMD 0.140, but lots of other things were broken. Inside a template, I've only got good use out of it by:
> 
> static if (n<=0) {
>   static assert(0, "factorial must be >=0");
> }


I've tried this approach too:

template factorial(int n)
{
    static if (n <= 0)
        static assert(0);
    static if (n == 1)
        const factorial = 1;
    else
        const factorial =
            n * factorial!(n-1);
}

int main()
{
    return factorial!(0);
}

It still doesn't work, no assert failure.

L.