
On Mon, Aug 19, 2013 at 10:38 AM, Mathias Gaunard < mathias.gaunard@ens-lyon.org> wrote:
On 18/08/13 21:41, Matt Calabrese wrote:
Mathias, do you have any reason for the assertion that it's "unnecessarily
inefficient" at compile time?
- It instantiates more templates (at least 4 instead of 1, and much worse if going through the function_traits path) - It increases symbol size. - It requires an additional name resolution and overload resolution step.
The first point is only true in the old implementation -- the one in the sandbox ditches the function type trick entirely and just directly instantiates an enable_if-style template. Right now, the template used inherits from boost::enable_if, but that inheritance can be eliminated if the additional instantiation implied by the base offends you. That would make the amount of instantiations exactly the same as a traditional enable_if approach Can you elaborate on your third point? What additional step are you talking about and show that it actually impacts compile-time. It's certainly possible that this approach has a compile-time impact over directly using enable_if, though I've used it extensively for over a year and haven't noticed. I haven't made a big, brute-force test for compile-time performance, but from the looks of it neither have you. Really I don't see how all that cost and portability concerns make it
worthwhile to write
template
)) int f(T const&) { return 0; } instead of
template<class T> typename enable_if< is_same
, int >::type f(T const&) { return 0; }
The former doesn't hide the return type and is also able to be used in more places. In the case of the traditional enable_if approach you have a few considerations. When working with constructors, you can only use the parameter form. When dealing with most operator overloads you can only use the return type form. You can't use the return type nor the parameter form at all in some places (variadic constructors, conversion operators, etc.). You also can't use traditional enable_if if your condition doesn't depend on a template parameter. On the other hand, every single one of the aforementioned cases works perfectly fine with the template argument list form (I.E. the macro approach). It's one tool that fits all and it clutters neither the return type nor the function parameter list, making the declaration easy to read and to write. Further, the "lazy" forms in the macro approach are more capable than the boost::lazy_enable_if family of templates, since the macro allows you to introduce multiple, named, evaluated lazy types, which can be each easily be referenced in multiple parts of the function declaration or function body. As for portability concerns, you could argue the same about any library that uses C++11. It's already 2 years since C++11, with C++1y likely coming next year. GCC also supported the features required for this macro before the standard was ratified. If you don't have a compiler capable of using the macro or if your code needs to be portable to 03 compilers, or if you are afraid it will noticeably impact compile-times (without actually testing it), there's nothing stopping you from using boost::enable_if instead. I do not propose removing boost::enable_if or std::enable_if. -- -Matt Calabrese