> On Aug 23, 2017, at 12:21 PM, Konstantin Tokarev <[email protected]> wrote: > > > > 23.08.2017, 21:15, "Keith Miller" <[email protected] > <mailto:[email protected]>>: >> 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. > > Actually, you need no parens: > > #define ENABLE_TEMPLATE_IF(...) typename = typename > std::enable_if<__VA_ARGS__>::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>(); > }
Oh, clever! I didn’t think of that. > > >> >> 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 <[email protected]> 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 <[email protected]> wrote: >>>> >>>>> On Aug 22, 2017, at 9:17 PM, JF Bastien <[email protected]> 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 <[email protected]> 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 <[email protected]> >>>>>> 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 >>>>>> [email protected] >>>>>> https://lists.webkit.org/mailman/listinfo/webkit-dev >>>> >>>> _______________________________________________ >>>> webkit-dev mailing list >>>> [email protected] >>>> https://lists.webkit.org/mailman/listinfo/webkit-dev >> >> _______________________________________________ >> webkit-dev mailing list >> [email protected] >> https://lists.webkit.org/mailman/listinfo/webkit-dev > > -- > Regards, > Konstantin
_______________________________________________ webkit-dev mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-dev

