explicit castable to bool for predicate restraints?

monarch_dodra monarchdodra at gmail.com
Mon Dec 17 01:23:45 PST 2012


I had a discussion a little while ago, regarding the validation 
of predicates.

Basically, fearing that someone may write a predicate that 
returned some weird user-defined type that wasn't bool-able, I 
wrote:

//----
void foo(Range, S)(Range r, S s)
    if (isForwardRange!Range && is(typeof(r.front == s) : bool))
{ ... }

or

void foo(alias pred, Range, S)(Range r, S s)
    if (isForwardRange!Range && is(typeof(unaryFun!pred(r.front)) 
: bool))
{ ... }
//----

I just realized that the problem with this (which I need to fix 
asap in phobos, since I was recently pulled), is that this test 
will fail if the predicate returned something that was not 
*implicitly* castable to bool, but still *explicitly* castable to 
bool. For example:

//----
int cmp()
{
     return 4;
}

void main()
{
     static if (cmp())
         static assert(is(typeof(cmp()) : bool)); //Here
}
//----

This code will enter the static if (which means the result of cmp 
*can* be used inside an if), however, it will fail the assert 
(here).

Conclusion: using `is(typeof(bla) : bool)` is bad form, as many 
(valid) comparators (and even opEquals) return int.

So the "better" test would be to test with cast(bool), as such:
//----
void foo(Range, S)(Range r, S s)
    if (isForwardRange!Range && is(typeof(cast(bool)(r.front == 
s)))
{ ... }

or

void foo(alias pred, Range, S)(Range r, S s)
    if (isForwardRange!Range && 
is(typeof(cast(bool)unaryFun!pred(r.front))))
{ ... }
//----

So here are my two questions:

1. Is there a more "elegant" way to write this test? Is there a 
more convenient "is explicitly castable syntax"?

2. Is this test even worth it? It bogs down the restriction 
(which needs to be as_clear_as_possible for our callers). Could 
we just say "Phobos expects any and all predicates to be useable 
in an if", and not bother?

On the one hand, it needs testing, but on the other, the check's 
"cognitive cost" could be too high...

Maybe we could have the functions match on any predicate return, 
but then consider that an invalid return type is a checked error 
(static assert)?

//----
void foo(Range, S)(Range r, S s)
    if (isForwardRange!Range && is(typeof(r.front == s))
{
     static assert(typeof(cast(bool)(r.front == s)), "The supplied 
predicate does not return a testable result.");
     ...
}
//----

Opinions? Just want to know how which direction to take my future 
developments.


More information about the Digitalmars-d mailing list