|
Boost : |
Subject: Re: [boost] New, powerful way to use enable_if in C++0x
From: Krzysztof Czainski (1czajnik_at_[hidden])
Date: 2011-04-11 17:07:23
2011/4/11 Matt Calabrese <rivorus_at_[hidden]>
> On Mon, Apr 11, 2011 at 3:34 PM, Gevorg Voskanyan <v_gevorg_at_[hidden]
> >wrote:
>
> > Nice! The idea is very useful and powerful indeed, and one I'd definitely
> > like
> > to see documented. I have a question however. Is there a particular
> reason
> > you
> > did it like:
> > typename boost::enable_if< boost::is_arithmetic< T > >::type*& =
> > boost::enabler
> > instead of:
> > typename Enable = typename boost::enable_if< boost::is_arithmetic< T >
> > >::type
> > ?
> > The latter seems clearer to me and removes the need to introduce a
> > boost::enabler identifier.
>
>
> It's necessary because otherwise with two overloads you'd end up with two
> declarations that differ only in default arguments, which would be a
> compile
> error. For instance, consider the following:
>
> //////////
> template< class T, class Enable = typename enable_if< is_arithmetic< T >
> >::type >
> void foo( T ) {}
>
> template< class T, class Enable = typename enable_if< is_pointer< T >
> >::type >
> void foo( T ) {}
> //////////
>
> This would be an error even though the conditions don't overlap! To better
> understand why, imagine it with the defaults removed. Both of them are
> actually declaring exactly the same function template with the only
> difference being that they use a different default. In other words both are
> declaring:
>
> //////////
> template< class T, class Enable >
> void foo( T );
> //////////
>
> however, you have provided two different defaults and two different
> definitions. This is, of course, an error.
>
> If the fact that they're templates is throwing you off, compare this to
> regular function argument defaults:
>
> //////////
> void bar( int arg = 5 ) {}
> void bar( int arg = 6 ) {}
> //////////
>
> This code has a similar problem to the code you posted above. Even though
> the defaults are different, they are still just declaring void bar( int );
> The fact that we are exploiting SFINAE with the default argument in the
> template example does not change that. We have to make substitution fail
> when forming template parameter type itself as opposed to just its default.
>
I love this! ;-)
Another drawback is the necesicy to use the typename keyword, which suggests
at first glance, that this is a type template parameter, while it actually
is a constant template parameter. The fact, that boost::enabler is hidden
from user view, so the user can't see it isn't a type, doesn't help.
For an alternative without boost::enabler, how about:
typename boost::enable_if< boost::is_arithmetic<T>, int >::type = 0
Regards
Kris
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk