23.08.2017, 21:15, "Keith Miller" <[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>();
 }


>
> 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

Reply via email to