Checking the Return Type of a Template Alias Parameter in assertCTFEable

John Colvin john.loughran.colvin at gmail.com
Fri Feb 28 08:19:07 PST 2014


On Friday, 28 February 2014 at 16:13:19 UTC, Nordlöw wrote:
> On Friday, 28 February 2014 at 15:03:29 UTC, John Colvin wrote:
>> On Friday, 28 February 2014 at 14:02:35 UTC, Nordlöw wrote:
>>> I have a solution to Issue 388 at
>>>
>>> https://github.com/nordlow/dmd/commits/master
>>>
>>> that works nicely for my projects.
>>>
>>> This patch however generates a handful of warnings in Phobos 
>>> unittests.
>>>
>>> All of these are IMO fixable except for one which I don't 
>>> know how to fix namely the definition of assertCTFEable in 
>>> exception.d
>>>
>>> I need to change this to explicitly capture the return value 
>>> of the template alias argument dg when this is non-void. My 
>>> try so far was to change
>>>
>>> version(unittest) package
>>> @property void assertCTFEable(alias dg)()
>>> {
>>>   static assert({ dg(); return true; }());
>>>   dg();
>>> }
>>>
>>> to
>>>
>>> version(unittest) package
>>> @property void assertCTFEable(alias dg)()
>>> {
>>>   static assert
>>>       ({
>>>           static if (is(typeof(db()) == void)) {
>>>               dg();
>>>           } else {
>>>               auto x = dg();
>>>           }
>>>           return true;
>>>       }());
>>>   static if (is(typeof(db()) == void)) {
>>>       dg();
>>>   } else {
>>>       auto x = dg();
>>>   }
>>> }
>>>
>>> gives the following error when in Phobos make unittest:
>>>
>>> std/exception.d(1392): Error: variable 
>>> std.exception.assertCTFEable!(function ()
>>> {
>>> S[] r = array(repeat((S __ctmp1582 = 0;
>>> , __ctmp1582).this(1), 2LU));
>>> assert(equal(r, [(S __ctmp1591 = 0;
>>> , __ctmp1591).this(1), (S __ctmp1592 = 0;
>>> , __ctmp1592).this(1)]));
>>> }
>>> ).assertCTFEable.__lambda1.x type void is inferred from 
>>> initializer (*function ()
>>> {
>>> S[] r = array(repeat((S __ctmp1582 = 0;
>>> , __ctmp1582).this(1), 2LU));
>>> assert(equal(r, [(S __ctmp1591 = 0;
>>> , __ctmp1591).this(1), (S __ctmp1592 = 0;
>>> , __ctmp1592).this(1)]));
>>> }
>>> )(), and variables cannot be of type void
>>> std/exception.d(1392): Error: expression (*function ()
>>> {
>>> S[] r = array(repeat((S __ctmp1582 = 0;
>>> , __ctmp1582).this(1), 2LU));
>>> assert(equal(r, [(S __ctmp1591 = 0;
>>> , __ctmp1591).this(1), (S __ctmp1592 = 0;
>>> , __ctmp1592).this(1)]));
>>> }
>>> )() is void and has no value
>>>
>>> How can I in a general way check if dg evaluates to void or 
>>> not?
>>
>> Either use std.traits.ReturnType, or see from it's 
>> implementation.
>
> I tried
>
>
> version(unittest) package
> @property void assertCTFEable(alias dg)()
> {
>     static assert
>         ({
>             static if (is(ReturnType!(db()) == void)) {
>                 dg();
>             } else {
>                 auto x = dg();
>             }
>             return true;
>         }());
>     static if (is(ReturnType!(db()) == void)) {
>         dg();
>     } else {
>         auto x = dg();
>     }
> }
>
> but this instead fails as
>
> std/exception.d(1392): Error: variable 
> std.conv.__unittestL932_18.assertCTFEable!(dg).assertCTFEable.__lambda1.x 
> type void is inferred from initializer dg(), and variables 
> cannot be of type void
> std/exception.d(1392): Error: expression dg() is void and has 
> no value
> std/exception.d(1402): Error: variable 
> std.conv.__unittestL932_18.assertCTFEable!(dg).assertCTFEable.x 
> type void is inferred from initializer dg(), and variables 
> cannot be of type void
> std/exception.d(1402): Error: expression dg() is void and has 
> no value
> std/conv.d(974): Error: template instance 
> std.conv.__unittestL932_18.assertCTFEable!(dg) error 
> instantiating
> std/exception.d(1392): Error: variable 
> std.exception.assertCTFEable!(function ()
> {
> assert(to(4611686018427387904LU) == "4611686018427387904");
> assert(to(4294967296L) == "4294967296");
> assert(to(-138L) == "-138");
> }
> ).assertCTFEable.__lambda1.x type void is inferred from 
> initializer (*function ()
> {
> assert(to(4611686018427387904LU) == "4611686018427387904");
> assert(to(4294967296L) == "4294967296");
> assert(to(-138L) == "-138");
> }
> )(), and variables cannot be of type void

Should be

version(unittest) package
@property void assertCTFEable(alias dg)()
{
     static assert
         ({
             static if (is(ReturnType!dg == void)) {
                 dg();
             } else {
                 auto x = dg();
             }
             return true;
         }());
     static if (is(ReturnType!dg == void)) {
         dg();
     } else {
         auto x = dg();
     }
}


More information about the Digitalmars-d mailing list