
On Mon, Apr 11, 2011 at 3:34 PM, Gevorg Voskanyan <v_gevorg@yahoo.com>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. -- -Matt Calabrese