Boost logo

Boost :

From: Paul Moore (gustav_at_[hidden])
Date: 1999-12-16 19:12:30


From: jsiek_at_[hidden] [mailto:jsiek_at_[hidden]]
>
> I have still not heard of (or come up with myself) a
> solution for this. As you've noticed, the obvious workarounds
> don't work because VC++ is so broken. Perhaps we just
> need to complain loudly to Microsoft. Does anyone have
> connections with people on their compiler/library team?
>

I've just found a solution. It seems to work, although I am fairly confused as
to the validity of it (or, for that matter, why it works!). I shall explain...

To summarise - we have

namespace boost {
...

// (1) - see below

template <typename I> inline rational<I> abs(const rational<I> &r)
{
    // (2) - see below
    return rational<I>(abs(r.num), r.den));
}

We want abs(r.num) to have no namespace qualification here, so that Koenig
lookup (where it is implemented - not on MSVC) will do the right thing when I is
a user-defined type - my key motivation here is to support use of a user-defined
BigInt type.

Now, to get the standard abs() for int and long, we need to import the
definitions from std::. I *believe* that the correct place to do that is at
point (2) with a "using std::abs" declaration. This needs protecting with a
BOOST_NO_STDC_NAMESPACE, as MSVC (and maybe others) doesn't have abs in std. Can
someone with a real compiler confirm that this using declaration works? [I can't
get mingw to compile it either - no <limits>, no std::iterator,... - is mingw
*really* a full C++ environment, the way people suggest?]

But with this setup, MSVC fails to resolve abs(int) - it seems to be only trying
the boost::abs version. I don't know why, but it's definitely the case. Now, to
get round this, I can (conditional on _MSC_VER) add a "using ::abs" declaration
at point (1). This imports ::abs into the boost namespace. It's pollution, but
probably not devastating - and it's only on MSVC, where the namespace stuff is a
mess anyway...

Actually, given that MSVC has ::abs and ::labs, maybe it would be better to
*implement* the overloaded abs() using

inline int abs(int n) { return ::abs(n); }
inline long abs(long n) { return ::labs(n); }

- otherwise rational<long> mightn't work properly.....

It also means that if someone implements MyNamespace::BigInt, they'll have to
add

#ifdef _MSC_VER
namespace boost { using MyNamespace::abs; }
#endif

to get the abs() resolution for boost::rational working, but that's not a major
disaster, I guess. And if I implement boost::bigint as my next project, then
it's there already :-)

I think I'm (relatively) happy with this resolution. If anyone has comments, let
me know, otherwise I'll package up a "final" version and send it out tomorrow.

Paul.


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