C++ guys hate static_if?

monarch_dodra monarchdodra at gmail.com
Sun Mar 10 09:05:36 PDT 2013


On Sunday, 10 March 2013 at 02:35:28 UTC, Walter Bright wrote:
> On 3/9/2013 8:22 AM, monarch_dodra wrote:
>> Things can get evenmore hairy,when you are operating on 2 
>> different types.
>
> This is why complex expressions can be encapsulated as 
> functions.

Yes, but that doesn't solve the "root" issue of meaningfulness. 
Sure, instead of having a 5 line constraint, it's only a single 
line, but are these any better?

sort(R, Scheme)(...)
     
if(isRandomAccessRangeWithComparableElementsAndAssignableElementsIfStableSchemeOrSwapableElementsOtherwise!R)

or

sort(...)
     if(meetsSortConstraints!R)

Neither are really any better for the end user.

This is why I don't think constraints should be used at all for 
validating arguments. [concepts|static asserts] are much better, 
and when combined with static if, become incredibly powerful:

sort(R, Scheme)(...)
{
     static assert (isRandomAccessRange!T);
     static assert (is(typeof(r.front < r.front)));
     static if (Scheme == Stable)
         static assert (hasAssignableElements!T);
     else
         static assert (hasSwapableElements!T);

     //Code Code Code
}

Much clearer, and the diagnostics much better.

That said, we can also look for a "middle ground" where the 
constraints validate the broad requirements (RA, comparable), and 
the asserts validate the more complex stuff.

>> One last thing to keep in mind is that having constraints 
>> allows hijacking,
>> whereas concpets/static asserts resolve as an ambigus call.
>
> I don't see where the hijacking comes in.

The problem with contraints is that it merelly eliminates 
functions from the pool of overloads. If you attemp to call a 
function with invalid parameters, then you may end up 
accidentally calling something you didn't want to. Imagine:

//----
module a;
void do_it(R)(R r)
     if (isForwardRange!R)
{
     //Do something to r
}
//----
module b;
void do_it(T)(T t)
{
     //Do something completely different
}
//----
import a, b;

void main()
{
     MyInputRange myInputRange; //Oops! I didn't realize it's only 
input:
     do_it(myInputRange); //meant to call a.do_it;
}
//----

With the current scheme of constraints, this will end up calling 
b.do_it, without any ambiguity. You may or may not consider that 
is "hijacking", but it is error prone.

NOW, if we had defined a.do_it with concepts/static asserts, the 
programmer would have been served with a "ambiguous call: a.do_it 
or b.do_it"? So the coder would have to be "alright, I want to 
explicitly call a.do_it". To which this time the compiler replies 
"Error: isForwardRange!MyInputRange is false". To which the 
programmer replies "I understand my error and see what I did 
wrong".

--------------------------------------

I'm not saying template constraints are bad or anything, I think 
they are incredible tools for dispatching to specialized 
overloads.

However, In regards to *validating* the input, I think 
concepts/static asserts, are both more robust 
implementation-wise, while being clearer for the end coder.


More information about the Digitalmars-d mailing list