| Thread overview | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
I should probably expand this question...
Who uses templates in D? What is the most complex use you've done? Do you ever plan to get more complex? Would SFINAE make your life easier or harder?
I've written templates classes that have one definition, and used static if as needed for specialization. I don't forsee more complex usage and view SFINAE as something that would mask bugs.
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.
| ||||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | Jason House wrote: > I should probably expand this question... > > Who uses templates in D? What is the most complex use you've done? Do you ever plan to get more complex? Would SFINAE make your life easier or harder? > > I've written templates classes that have one definition, and used static if as needed for specialization. I don't forsee more complex usage and view SFINAE as something that would mask bugs. I don't have time to write more right now, but Lutz Kettner gives a pretty good examples of using SFINAE here: http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/meta.html#Constraining http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/meta.html#Classification Certainly the Enable_if template can be replaced by a simple static if. Maybe the other one too. The main problem I have with templates in D is that traits templates are severely limited by the inability to define specializations for a template in different modules. Like the IsVector_2 template Lutz talks about. If all specializations have to be in one file, then the library designer has to know in advance all the types that can ever be used as a Vector2 and clearly that limits the utility of it. Maybe this is coming in D2. I think I did a test recently and it still didn't work. --bb | |||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | I look forward to when you can write more... Are you trying to say SFINAE is needed? I look at the examples and still think probably not. The traits example can be solved cleanly in D, just like enable if. The toughest one is the vector 2 example. I think detection of what is a vector 2 could be done with an interface? The rest of the examples I reaf are SFINAE free.
Bill Baxter Wrote:
> Jason House wrote:
> > I should probably expand this question...
> >
> > Who uses templates in D? What is the most complex use you've done? Do you ever plan to get more complex? Would SFINAE make your life easier or harder?
> >
> > I've written templates classes that have one definition, and used static if as needed for specialization. I don't forsee more complex usage and view SFINAE as something that would mask bugs.
>
> I don't have time to write more right now, but
> Lutz Kettner gives a pretty good examples of using SFINAE here:
> http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/meta.html#Constraining
> http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/meta.html#Classification
>
> Certainly the Enable_if template can be replaced by a simple static if. Maybe the other one too.
>
> The main problem I have with templates in D is that traits templates are severely limited by the inability to define specializations for a template in different modules. Like the IsVector_2 template Lutz talks about. If all specializations have to be in one file, then the library designer has to know in advance all the types that can ever be used as a Vector2 and clearly that limits the utility of it.
>
> Maybe this is coming in D2. I think I did a test recently and it still didn't work.
>
>
>
> --bb
| |||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | I was looking around for something good on traits templates, the hows and whys. This seems to be pretty decent: http://www.cantrip.org/traits.html --bb | |||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | The description of traits in Boost is quite succinct and hits the good points -- particularly about the non-intrusive part: http://www.boost.org/more/generic_programming.html#traits I think most traits-like things can be done in D if you require that people modify their classes. But the non-intrusiveness is one of key parts of what makes traits templates a good building block. --bb | |||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | Jason House wrote: > I should probably expand this question... > > Who uses templates in D? What is the most complex use you've done? Do you ever plan to get more complex? Would SFINAE make your life easier or harder? Templates are utterly necessary and horribly untestable. I use them, but I try to keep them as braindead simple as possible. I've done a reasonable amount of work with simple templates, eg DUnit's assertions, and some slightly more complex stuff, as with DMocks, but nothing incredibly difficult. DMocks was mainly a matter of looping through reflection information and assembling some strings based on that, which wasn't so difficult; the hardest thing (besides debugging CTFE failures and oddities with mixins, but I did my best to limit the amount of both) was not being able to have a variable whose type was an empty tuple. I had to wrap the tuple in a templated class that would just not instantiate the arguments variable with an empty tuple. SFINAE isn't a problem for me -- I don't need to overload templates much. If I did, I'd do it like this: template Foo(T, U, V...) { static if (condition1) { alias FooSpecialization1!(T, U, V) Foo; } else // ... } The only thing the compiler could do to help me that it isn't doing is to make it an error to have overloaded templates. > I've written templates classes that have one definition, and used static if as needed for specialization. I don't forsee more complex usage and view SFINAE as something that would mask bugs. Same. The only issue is with templates from different modules or libraries. In this case, it could be helpful for the compiler to have an error message along the lines of: template instantiation Foo!(int, float, float, char[]): could not instantiate. Candidates are: valhalla.odin.Foo(T : long, U, T, V[char]) : char[] is not a V[char] valhalla.thor.Foo(T : class, U...) : int is not a class ... | |||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter Wrote:
> The description of traits in Boost is quite succinct and hits the good points -- particularly about the non-intrusive part: http://www.boost.org/more/generic_programming.html#traits
>
> I think most traits-like things can be done in D if you require that people modify their classes. But the non-intrusiveness is one of key parts of what makes traits templates a good building block.
>
> --bb
If D could load specializations in another module, generalized traits could be done in D. In fact, I'd argue that SFINAE would hide bugs in user-supplied template code.
| |||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Ok, so you're saying you could do without SFINAE?
Christopher Wright Wrote:
> Jason House wrote:
> > I should probably expand this question...
> >
> > Who uses templates in D? What is the most complex use you've done? Do you ever plan to get more complex? Would SFINAE make your life easier or harder?
>
> Templates are utterly necessary and horribly untestable. I use them, but I try to keep them as braindead simple as possible.
>
> I've done a reasonable amount of work with simple templates, eg DUnit's assertions, and some slightly more complex stuff, as with DMocks, but nothing incredibly difficult.
>
> DMocks was mainly a matter of looping through reflection information and assembling some strings based on that, which wasn't so difficult; the hardest thing (besides debugging CTFE failures and oddities with mixins, but I did my best to limit the amount of both) was not being able to have a variable whose type was an empty tuple. I had to wrap the tuple in a templated class that would just not instantiate the arguments variable with an empty tuple.
>
> SFINAE isn't a problem for me -- I don't need to overload templates much. If I did, I'd do it like this:
>
> template Foo(T, U, V...)
> {
> static if (condition1)
> {
> alias FooSpecialization1!(T, U, V) Foo;
> }
> else
> // ...
> }
>
> The only thing the compiler could do to help me that it isn't doing is to make it an error to have overloaded templates.
>
> > I've written templates classes that have one definition, and used static if as needed for specialization. I don't forsee more complex usage and view SFINAE as something that would mask bugs.
>
> Same. The only issue is with templates from different modules or libraries.
>
> In this case, it could be helpful for the compiler to have an error message along the lines of:
>
> template instantiation Foo!(int, float, float, char[]): could not
> instantiate.
> Candidates are:
> valhalla.odin.Foo(T : long, U, T, V[char]) : char[] is not a V[char]
> valhalla.thor.Foo(T : class, U...) : int is not a class
> ...
| |||
March 22, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | Jason House wrote:
> Ok, so you're saying you could do without SFINAE?
Yes, and I wish I could do without templates.
| |||
March 24, 2008 Re: "SFINAE is Evil" | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | > Bill Baxter Wrote: > >> Jason House wrote: >>> I should probably expand this question... >>> >>> Who uses templates in D? What is the most complex use you've done? Do you ever plan to get more complex? Would SFINAE make your life easier or harder? >>> >>> I've written templates classes that have one definition, and used static if as needed for specialization. I don't forsee more complex usage and view SFINAE as something that would mask bugs. >> I don't have time to write more right now, but >> Lutz Kettner gives a pretty good examples of using SFINAE here: >> http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/meta.html#Constraining >> http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/meta.html#Classification Jason House wrote: > I look forward to when you can write more... Are you trying to say SFINAE is needed? Yes, I'm saying I haven't yet found a case where I'm using it (but that doesn't mean there isn't one!) However, I did start a thread a while back about a way to introduce /controlled/ SFINAE. Or rather a way to explicitly say you want to try something, and if it does generate an error, try something else. Compile time try-catch. Look for the subject "static try catch construct would be helpful" in this newsgroup. I still think that would be useful. > I look at the examples and still think probably not. Yes, with those examples I agree with you. They only use that Enable_if template which is easily replaced by a static if. > The traits example can be solved cleanly in D, just like enable if. > The toughest one is the vector 2 example. I think detection of what is a vector 2 could be done with an interface? The rest of the examples I read are SFINAE free. Yes, well the vector2 one is the important one (but the parts that have to do with SFINAE aren't the problem). The traits templates can be thought of like compile-time adapters or facades. So they are like compile-time interfaces in a way. But they are non-intrusive. Fred provides library Foo. Barny provides type Bar. Wilma wants to use Barny's Bar with Fred's Foo, but Fred and Barney designed their code separately and the interfaces are compatible. So what traits templates do is give Fred's Foo a way to /ask Wilma/ what to do with Barney's Bar without having to get Barney involved. Wilma provides a FooTraits!(T:Bar) specialization, and Fred's Foo instantiates it and uses that to find out what it needs to know. Of course this presumes Fred designed Foo with this sort of flexibility in mind. Ok, so now that I've written all that out explicitly, I see that one nice but unessential thing about Traits as I've described them is that it operates in a "pull" manner. That is, when Wilma tries to create a Foo!(Bar), Foo just turns around and tries to instantiate a FooTraits!(Bar), which could come from anywhere (in C++ anyway), and in this case it comes from Wilma's code. So this can be worked around in D. It just requires switching to a "push" model. And that means the FooTraits must become an extra template parameter to Foo. So instead of Wilma just instantiating a Foo!(Bar) with the traits automatically ferreted out internally as FooTraits!(Bar), Wilma will need to explicitly pass the traits, like Foo!(Bar, WilmasFooTraitsForBar). So I guess it's not the end of the world. I can't think of any reason off the top of my head that using the push model would be a show stopper. It just isn't quite as slick. I guess it makes things difficult for function templates though. No IFTI if you have to provide a traits parameter explicitly. --bb | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply