|
Boost Users : |
From: David Abrahams (dave_at_[hidden])
Date: 2006-11-12 12:23:46
"Michael Marcin" <mmarcin_at_[hidden]> 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
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net