Boost logo

Boost :

Subject: Re: [boost] Is there BOOST_ENABLE_IF macro now?
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2013-08-19 11:40:25


On Mon, Aug 19, 2013 at 10:38 AM, Mathias Gaunard <
mathias.gaunard_at_[hidden]> 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<class T, BOOST_ENABLE_IF(is_same<T, float>))
> int f(T const&)
> {
> return 0;
> }
>
> instead of
>
> template<class T>
> typename enable_if< is_same<T, float>
> , 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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk