Thread overview
"SFINAE is Evil"
Mar 21, 2008
Jason House
Mar 21, 2008
Craig Black
Mar 21, 2008
Bill Baxter
Mar 21, 2008
Russell Lewis
Mar 22, 2008
Russell Lewis
Mar 22, 2008
Jason House
Mar 24, 2008
Russell Lewis
March 21, 2008
SFINAE - Substitution failure is not an error

This post is all about templates and their static if counterparts.  With the enhanced expressiveness of D, is there a need for SFINAE from C++? Essentially, when a specialization exists, if the compilation of the specialization fails, the compiler silently gives up on it and goes to the next more general case.  In my mind, this is both dangerous and a loop hole for long compile times (as the compiler instantiates extra template instances).

What I want to know is this:  Who uses SFINAE in D, and why?  Is this a matter of convenience or a requirement.  If required, I assume it's from a lack of expressiveness in defining a template's conditions.  Could this be overcome with use of static if's instead?

PS: Post title is a quote of Russell Lewis from another thread.
March 21, 2008
"Jason House" <jason.james.house@gmail.com> wrote in message news:frv6ut$2ecv$1@digitalmars.com...
> SFINAE - Substitution failure is not an error
>
> This post is all about templates and their static if counterparts.  With the
> enhanced expressiveness of D, is there a need for SFINAE from C++?
> Essentially, when a specialization exists, if the compilation of the
> specialization fails, the compiler silently gives up on it and goes to the
> next more general case.  In my mind, this is both dangerous and a loop hole
> for long compile times (as the compiler instantiates extra template
> instances).
>
> What I want to know is this:  Who uses SFINAE in D, and why?  Is this a
> matter of convenience or a requirement.  If required, I assume it's from a
> lack of expressiveness in defining a template's conditions.  Could this be
> overcome with use of static if's instead?
>
> PS: Post title is a quote of Russell Lewis from another thread.

I get the feeling that a number of features in D can eventually be dumped in favor of others.  Perhaps SFINAE is one of them.  I haven't used templates in D enough to know for sure.  Definitely worth discussing though IMO. Anything that reduces the complexity of D without sacrificing expressive power is a good thing.

-Craig 

March 21, 2008
Jason House wrote:
> SFINAE - Substitution failure is not an error
> 
> This post is all about templates and their static if counterparts.  With the
> enhanced expressiveness of D, is there a need for SFINAE from C++? Essentially, when a specialization exists, if the compilation of the
> specialization fails, the compiler silently gives up on it and goes to the
> next more general case.  In my mind, this is both dangerous and a loop hole
> for long compile times (as the compiler instantiates extra template
> instances).
> 
> What I want to know is this:  Who uses SFINAE in D, and why?  Is this a
> matter of convenience or a requirement.  If required, I assume it's from a
> lack of expressiveness in defining a template's conditions.  Could this be
> overcome with use of static if's instead?
> 
> PS: Post title is a quote of Russell Lewis from another thread.


How do I know if I'm using SFINAE or not?  :-)

Seriously, I might be using it.  I'm not sure.  I'm not sure how to go about checking.  And that in and of itself seems like an undesirable quality.

I will say that I have most definitely been bitten by errors that came from failure to instantiate the template I thought I was instantiating (most often due to IFTI failures).  These things can usually be debugged by switching the code I suspect to specify all template arguments.  Then I'll get the sensible error telling me why it doesn't match.

Also I've had bugs from the is-expressions not getting triggered because I had a typo in the is-expression which wasn't a syntax error.  Not sure how the compiler could help there, though.

--bb
March 21, 2008
Bill Baxter wrote:
> How do I know if I'm using SFINAE or not?  :-)
> 
> Seriously, I might be using it.  I'm not sure.  I'm not sure how to go about checking.  And that in and of itself seems like an undesirable quality.

Indeed!

> I will say that I have most definitely been bitten by errors that came from failure to instantiate the template I thought I was instantiating (most often due to IFTI failures).  These things can usually be debugged by switching the code I suspect to specify all template arguments.  Then I'll get the sensible error telling me why it doesn't match.

Tuples hurt you here, because if you specify some Tuple template as a "last resort" template, you can end up using it for things you thought you'd handled.  Or, at least, I think that maybe that's the case...with SFINAE, it's hard to know for sure.
March 22, 2008
Jason House wrote:
> SFINAE - Substitution failure is not an error
> 
> This post is all about templates and their static if counterparts.  With the
> enhanced expressiveness of D, is there a need for SFINAE from C++?

Here's a classic example of how SFINAE makes things hard.  Look at the code below.  You'd expect the static assert to fail, right?  Give you an error message at the right location, and point you towards your bug?

Nope.

BEGIN CODE
  import std.stdio;

  template foo(TPL...)
  {
    static assert(false);
  }

  void main()
  {
    int i;
    foo!(i)();
  }
END CODE

Here's what the compiler actually says:
  sfinae.d(3): template sfinae.foo(TPL...) is not a function template
  sfinae.d(11): template sfinae.foo(TPL...) cannot deduce template function from argument types !(i)()

Not even a mention of the real problem.  Now imagine that you are using non-trivial templates!

Russ
March 22, 2008
It looks like your first compiler error is correct... There is no function.

> Jason House wrote:
> > SFINAE - Substitution failure is not an error
> > 
> > This post is all about templates and their static if counterparts.  With the enhanced expressiveness of D, is there a need for SFINAE from C++?
> 
> Here's a classic example of how SFINAE makes things hard.  Look at the code below.  You'd expect the static assert to fail, right?  Give you an error message at the right location, and point you towards your bug?
> 
> Nope.
> 
> BEGIN CODE
>    import std.stdio;
> 
>    template foo(TPL...)
>    {
>      static assert(false);
>    }
> 
>    void main()
>    {
>      int i;
>      foo!(i)();
>    }
> END CODE
> 
> Here's what the compiler actually says:
>    sfinae.d(3): template sfinae.foo(TPL...) is not a function template
>    sfinae.d(11): template sfinae.foo(TPL...) cannot deduce template
> function from argument types !(i)()
> 
> Not even a mention of the real problem.  Now imagine that you are using non-trivial templates!
> 
> Russ

March 24, 2008
Jason House wrote:
> It looks like your first compiler error is correct... There is no function.

You were right.  I've seen that error so many times before, in cases, where a function did exist, that I didn't look closely enough.  Here's a better example.  The following code will produce useless "not a function template errors."

Obviously, if you comment out the "static assert(false);", it works just fine.


BEGIN dmd OUTPUT
sfinae.d(3): template sfinae.foo(int I) is not a function template
sfinae.d(22): template sfinae.foo(int I) cannot deduce template function from argument types !(5)()
END OUTPUT


BEGIN CODE
import std.stdio;

template foo(int I)
{
  static if(I == 1)
  {
    void foo() {};
  }
  else
  {
    void foo()
    {
      static assert(false);
      foo!(1)();
      foo!(I-1)();
    }
  }
}

void main()
{
  foo!(5)();
}
END CODE