You can totally have the enable_if in the template list: #define ENABLE_TEMPLATE_IF(condition) typename = typename std::enable_if<condition>::type
template<typename T, ENABLE_TEMPLATE_IF((std::is_same<T, int>::value))> int foo() { return 0; } template<typename T, ENABLE_TEMPLATE_IF((std::is_same<T, double>::value))> double foo() { return 0; } int myFunction() { return foo<int>(); } Compiles fine for me. There is another downside to the macros though. Since they will probably have a comma in them C++ thinks that comma is meant to distinguish arguments to the macro... The only work around I know of is to wrap the argument in parens as I did above. I think mark’s case doesn’t work with my proposal so that’s convinced me that the template argument is the way to go. Although, I still think we should use the macro. Any objections? Cheers, Keith > On Aug 23, 2017, at 7:28 AM, Mark Lam <mark....@apple.com> wrote: > > One application of enable_if I’ve needed in the past is where I want > specialization of a template function with the same argument signatures, but > returning a different type. The only way I know to make that happen is to > use enable_if in the return type, e.g. > > std::enable_if<std::is_integral<T>, T>::type doStuff() { } > std::enable_if<std::is_double<T>, T>::type doStuff() { } > > This works around the problem of “duplicate function definitions” which > arises if the enable_if is not in the function signature itself. So, I’m not > sure your ENABLE_TEMPLATE_IF macro will give me a solution for this. > > Mark > > >> On Aug 22, 2017, at 11:14 PM, Keith Miller <keith_mil...@apple.com> wrote: >> >>> On Aug 22, 2017, at 9:17 PM, JF Bastien <j...@chromium.org> wrote: >>> >>> I'd suggest considering what it'll look like when we're migrating to >>> concepts in C++20. >>> >>> Here's an example for our bitwise_cast: >>> https://github.com/jfbastien/bit_cast/blob/master/bit_cast.h#L10 >>> >>> Notice the 3 ways to enable. There's also the option of using enable_if on >>> the return value, or as a defaulted function parameter, but I'm not a huge >>> fan of either. >> >> I think the concepts approach is the cleanest. I’d avoid the macro if we go >> that way. >> >> But C++20 is a long way away and I only expect this problem to get worse >> over time. So I’d rather find a nearer term solution. >> >>> On Aug 22, 2017, at 9:13 PM, Chris Dumez <cdu...@apple.com> wrote: >>> >>> I personally prefer std::enable_if<>. For e.g. >>> >>> template<typename T, class = typename std::enable_if<std::is_same<T, >>> int>::value> >>> Class Foo { } >> >> I just find this much harder to parse since I now have to: >> >> 1) recognize that the last class is not a actually polymorphic parameter >> 2) figure out exactly what the condition is given that it’s hidden inside an >> enable_if* >> >> The plus side of using a static_assert based approach is that it doesn’t >> impact the readability of function/class signature at a high level since >> it’s nested inside the body. It’s also not hidden particularly hidden since >> I would expect it to be the first line of the body >> >> Another downside of enable_if as a default template parameter is that >> someone could make a mistake and pass an extra template value, e.g. >> Foo<float, int>, and it might pick the wrong template parameter. This isn’t >> super likely but it’s still a hazard. >> >> Admittedly, we could make a macro like (totes not stolen from JF’s GitHub): >> >> #define ENABLE_TEMPLATE_IF(condition) typename = typename >> std::enable_if<condition>::type >> >> and implement Foo as: >> >> template<typename T, ENABLE_TEMPLATE_IF(std::is_same<T, int>::value)> >> class Foo { }; >> >> I think this approach is pretty good, although, I think I care about the >> enable_if condition rarely enough that I’d rather not see it in the >> signature. Most of the time the code will look like: >> >> template<typename T, ENABLE_TEMPLATE_IF(std::is_same<T, int>::value)> >> class Foo {...}; >> >> template<typename T, ENABLE_TEMPLATE_IF(std::is_same<T, float>::value)> >> class Foo {...}; >> >> template<typename T, ENABLE_TEMPLATE_IF(std::is_same<T, double>::value)> >> class Foo {...}; >> >> So when I know I want to use a Foo but I forgot the signature I now need to >> look mentally skip the enable_if macro, which I’d rather avoid. >> >>> >>> I don’t like that something inside the body of a class / function would >>> cause a template to be enabled or not. >> >> I believe there are cases where this already basically already happens e.g. >> bitwise_cast. Although, I think those cases could be fixed with a more >> standard approach. >> >> Cheers, >> Keith >> >>> >>> -- >>> Chris Dumez >>> >>> >>> >>> >>>> On Aug 22, 2017, at 8:34 PM, Keith Miller <keith_mil...@apple.com> wrote: >>>> >>>> Hello fellow WebKittens, >>>> >>>> I’ve noticed over time that we don’t have standard way that we enable >>>> versions of template functions/classes (flasses?). For the most part it >>>> seems that people use std::enable_if, although, it seems like it is >>>> attached to every possible place in the function/class. >>>> >>>> I propose that we choose a standard way to conditionally enable a template. >>>> >>>> There are a ton of options; my personal favorite is to add the following >>>> macro: >>>> >>>> #define ENABLE_TEMPLATE_IF(condition) static_assert(condition, “template >>>> disabled”) >>>> >>>> Then have every function do: >>>> >>>> template<typename T> >>>> void foo(…) >>>> { >>>> ENABLE_TEMPLATE_IF(std::is_same<T, int>::value); >>>> … >>>> } >>>> >>>> And classes: >>>> >>>> template<typename T> >>>> class Foo { >>>> ENABLE_TEMPLATE_IF(std::is_same<T, int>::value); >>>> }; >>>> >>>> I like this proposal because it doesn’t obstruct the signature/declaration >>>> of the function/class but it’s still obvious when the class is enabled. >>>> Obviously, I think we should require that this macro is the first line of >>>> the function or class for visibility. Does anyone else have thoughts or >>>> ideas? >>>> >>>> Cheers, >>>> Keith >>>> >>>> P.S. in case you are wondering why this macro works (ugh C++), it’s >>>> because if there is any compile time error in a template it cannot be >>>> selected as the final candidate. In my examples, if you provided a type >>>> other than int foo/Foo could not be selected because the static_assert >>>> condition would be false, which is a compile error. >>>> _______________________________________________ >>>> webkit-dev mailing list >>>> webkit-dev@lists.webkit.org >>>> https://lists.webkit.org/mailman/listinfo/webkit-dev >>> >> >> _______________________________________________ >> webkit-dev mailing list >> webkit-dev@lists.webkit.org >> https://lists.webkit.org/mailman/listinfo/webkit-dev > _______________________________________________ webkit-dev mailing list webkit-dev@lists.webkit.org https://lists.webkit.org/mailman/listinfo/webkit-dev