"Michael Marcin" <mmarcin@method-solutions.com> writes:
Hello,
I have a fixed point math class and I want to enable some optimized operator overloads.
for instance:
fixed& fixed::operator /= ( const fixed &rhs ); fixed& fixed::operator /= ( int n );
it seems however to me that what I really want is an overload like:
template< typename T > fixed& operator /= ( typename boost::enable_if<boost::is_integral<T>,T>::type n );
However I can't seem to get that function considered for overload resolution
Because your type T there is in a nondeduced context. You need template < typename T > boost::enable_if<boost::is_integral<T>,fixed&> operator/=(T n)
Speaking of which I don't understand why the following doesn't work in place of the previous constructor.
template< typename T > fixed::fixed( typename boost::enable_if< boost::is_integral<T>,T>::type n );
Again, nondeduced context. What you're trying to ask the compiler to do when you call that constructor is to find T such that enable_if<is_integral<T>,T>::type is the same as the argument type. But there could in principle be many such Ts depending on the definitions of enable_if and is_integral. The compiler doesn't know that enable_if happens to be defined so that there is a unique T that satisfies that condition, and more importantly, C++ compilers aren't required to do that sort of deduction. template <class T> struct id; template <class T> void f(typename id<T>::type); looks simple, right? template <class T> struct id { typedef int type; }; // uh-oh now let's
Finally I'm using this class to replace a lot of hardcoded / macro logic and often as an optimization the code uses binary shifts to represent power of 2 multiply/divides. Going forward these divides need to work with both fixed and floating point types so f >> 1 needs to change to f / 2. Is it possible to create an overload for the / and * operators that determine if the operand is an integral constant and is a power of 2 and use a binary shift internally?
The only way you'll be able to detect power-of-2-ness at overload resolution time is if you pass the number at compile-time: // UNTESTED! typedef mpl::integral_c<unsigned,1> one; template <class N> struct is_power_of_2 : mpl::or_< mpl::less_equal<N,one> , mpl::and_< mpl::not_<mpl::bitand<N,one> > , is_power_of_2<mpl::shift_right<N,one> > > > {}; template <class T> enable_if<is_power_of_2<T>, int> f(T) { return 0; } int x = f(mpl::int_<16>()); // OK int y = f(mpl::int_<5>()); // compile-time error -- Dave Abrahams Boost Consulting www.boost-consulting.com