digitalmars.D - Re: "SFINAE is Evil"
- Jason House <jason.james.house gmail.com> Mar 21 2008
- Bill Baxter <dnewsgroup billbaxter.com> Mar 22 2008
- Jason House <jason.james.house gmail.com> Mar 22 2008
- Bill Baxter <dnewsgroup billbaxter.com> Mar 22 2008
- Bill Baxter <dnewsgroup billbaxter.com> Mar 22 2008
- Jason House <jason.james.house gmail.com> Mar 22 2008
- Bill Baxter <dnewsgroup billbaxter.com> Mar 23 2008
- Jason House <jason.james.house gmail.com> Mar 24 2008
- Georg Wrede <georg nospam.org> Mar 25 2008
- Bill Baxter <dnewsgroup billbaxter.com> Mar 25 2008
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Mar 25 2008
- Jason House <jason.james.house gmail.com> Mar 25 2008
- Bill Baxter <dnewsgroup billbaxter.com> Mar 25 2008
- Jason House <jason.james.house gmail.com> Mar 26 2008
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Mar 26 2008
- Christopher Wright <dhasenan gmail.com> Mar 22 2008
- Jason House <jason.james.house gmail.com> Mar 22 2008
- Christopher Wright <dhasenan gmail.com> Mar 22 2008
- Georg Wrede <georg nospam.org> Mar 25 2008
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.
Mar 21 2008
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
Mar 22 2008
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
Mar 22 2008
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
Mar 22 2008
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
Mar 22 2008
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
Mar 22 2008
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?
or harder?I've written templates classes that have one definition, and used
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:
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
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
Mar 23 2008
Bill Baxter wrote: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 also had the feeling of "SFINAE is needed, but I can't come up with any examples". I find it interesting that nobody posted a need for SFINAE. Because of that, and all the pitfalls, I agree that SFINAE as a default behavior is undesirable and should disapear from D. Rather than propose an alternative to it, I wanted to understand how it should be used in D. With no examples of it, I've started leaning toward simple removal of it. I started this thread thinking the likely outcome would be something like your proposal. Now I'm thinking that SFINAE is not needed. If that's not true, I'm thinking it may be better to enhance is clauses and/or CTFE to cover the (small) capability gap. What do you think of that? If you (and others paying attention to this thread) agree, how do we get the attention of Walter? Maybe it should be a feature request or an entry on the unofficial D wishlist?
Mar 24 2008
Jason House wrote:I also had the feeling of "SFINAE is needed, but I can't come up with any examples". I find it interesting that nobody posted a need for SFINAE. Because of that, and all the pitfalls, I agree that SFINAE as a default behavior is undesirable and should disapear from D. Rather than propose an alternative to it, I wanted to understand how it should be used in D. With no examples of it, I've started leaning toward simple removal of it. I started this thread thinking the likely outcome would be something like your proposal. Now I'm thinking that SFINAE is not needed. If that's not true, I'm thinking it may be better to enhance is clauses and/or CTFE to cover the (small) capability gap. What do you think of that? If you (and others paying attention to this thread) agree, how do we get the attention of Walter? Maybe it should be a feature request or an entry on the unofficial D wishlist?
I suspect it would be quite simple to add a compiler switch to turn SFINAE on or off? Since D2 is "experimental" anyway, we might have this switch for a few months, and then see if anybody actually used it. The default would be SF is an error.
Mar 25 2008
Georg Wrede wrote:Jason House wrote:I also had the feeling of "SFINAE is needed, but I can't come up with any examples". I find it interesting that nobody posted a need for SFINAE. Because of that, and all the pitfalls, I agree that SFINAE as a default behavior is undesirable and should disapear from D. Rather than propose an alternative to it, I wanted to understand how it should be used in D. With no examples of it, I've started leaning toward simple removal of it. I started this thread thinking the likely outcome would be something like your proposal. Now I'm thinking that SFINAE is not needed. If that's not true, I'm thinking it may be better to enhance is clauses and/or CTFE to cover the (small) capability gap. What do you think of that? If you (and others paying attention to this thread) agree, how do we get the attention of Walter? Maybe it should be a feature request or an entry on the unofficial D wishlist?
I suspect it would be quite simple to add a compiler switch to turn SFINAE on or off? Since D2 is "experimental" anyway, we might have this switch for a few months, and then see if anybody actually used it. The default would be SF is an error.
That would be great. I'd love to try out such a switch. Though at the moment it would do me no good unless it were added to D1 also. Though rather than turning it off, I'd rather have a -v kind of switch that prints out a message whenever SFINAE is invoked, maybe with an instantiation stack trace. --bb
Mar 25 2008
"Bill Baxter" <dnewsgroup billbaxter.com> wrote in message news:fsbp54$293h$1 digitalmars.com...That would be great. I'd love to try out such a switch. Though at the moment it would do me no good unless it were added to D1 also. Though rather than turning it off, I'd rather have a -v kind of switch that prints out a message whenever SFINAE is invoked, maybe with an instantiation stack trace.
Great idea! <narrator>And with that, the suggestion began its slow, painful descent into the depths of the unread old posts of the NG, never to be seen again or commented on by the very man who could make a difference. Months later many would reminisce about what a good idea it was, and would sigh nostalgically over their youthful optimism.</narrator>
Mar 25 2008
Jarrett Billingsley wrote:"Bill Baxter" <dnewsgroup billbaxter.com> wrote in message <narrator>And with that, the suggestion began its slow, painful descent into the depths of the unread old posts of the NG, never to be seen again or commented on by the very man who could make a difference. Months later many would reminisce about what a good idea it was, and would sigh nostalgically over their youthful optimism.</narrator>
That about sums it up :(
Mar 25 2008
Jason House wrote:Jarrett Billingsley wrote:"Bill Baxter" <dnewsgroup billbaxter.com> wrote in message <narrator>And with that, the suggestion began its slow, painful descent into the depths of the unread old posts of the NG, never to be seen again or commented on by the very man who could make a difference. Months later many would reminisce about what a good idea it was, and would sigh nostalgically over their youthful optimism.</narrator>
That about sums it up :(
Yes, sweet. Someone should post a self-referential url in this thread so it will be easier to find and refer to it later. :-) --bb
Mar 25 2008
Jarrett Billingsley wrote:"Bill Baxter" <dnewsgroup billbaxter.com> wrote in message news:fsbp54$293h$1 digitalmars.com...That would be great. I'd love to try out such a switch. Though at the moment it would do me no good unless it were added to D1 also. Though rather than turning it off, I'd rather have a -v kind of switch that prints out a message whenever SFINAE is invoked, maybe with an instantiation stack trace.
Great idea! <narrator>And with that, the suggestion began its slow, painful descent into the depths of the unread old posts of the NG, never to be seen again or commented on by the very man who could make a difference. Months later many would reminisce about what a good idea it was, and would sigh nostalgically over their youthful optimism.</narrator>
I created an enhancement request (#1951) for this. That should (hopefully) gain visibility with Walter (and more importantly?) Andrei, who's been known to fully flex C++'s templates. Feel free to add individual ideas on what might be a good alternative to SFINAE. I really didn't put any in the enhancement request.
Mar 26 2008
Bill Baxter wrote: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/me a.html#Constraining http://www.mpi-inf.mpg.de/~kettner/courses/lib_design_03/notes/meta html#Classification
Upon reading that, it's amazing how much more simple(and powerful) meta-programming is in D. (having static if, is-expressions, aliases, and D template syntax) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Mar 26 2008
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 ...
Mar 22 2008
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 ...
Mar 22 2008
Jason House wrote:Ok, so you're saying you could do without SFINAE?
Yes, and I wish I could do without templates.
Mar 22 2008
Christopher Wright wrote:Jason House wrote:Ok, so you're saying you could do without SFINAE?
Yes, and I wish I could do without templates.
I don't need templates. But that's probably because I only do apps. If I were to write libraries (even for myself), then I'd expect to be using templates in many, if not most of the functions. I's just that I currently don't run into things where I'd need a template. As for SFINAE, I can't even imagine where I'd gain with it.
Mar 25 2008