Boost logo

Boost :

From: helmut.zeisel_at_[hidden]
Date: 2001-08-09 09:49:29


In some cases, it might be useful to
overwrite the default implementation of rational_cast
(e.g. if the numerator or the denominator
is not represantable as double, but their quotient is).

Trying this, GCC 3.0 gives the following diagnosis:

#include <boost/rational.hpp>
class A{};
namespace boost
{
  template<typename T> T rational_cast(const rational<A>& a){return
0;}
};
int main()
{
  boost::rational<A> a;
  double d=boost::rational_cast<double>(a);
  return 0;
}

c++ main.cxx
main.cxx: In function `int main()':
main.cxx:10: call of overloaded
     `rational_cast(boost::rational<A>&)' is ambiguous
/usr/local/include/boost/rational.hpp:501:
   candidates are: T
   boost::rational_cast(const boost::rational<IntType>&)
   [with T = double, IntType = A]
r.cxx:5: T boost::rational_cast(const boost::rational<A>&)
   [with T = double]

As I understand, GCC 3.0 is right,
because the standard is somewhat unclear in that respect:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_closed.html#200
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#250

A possible workaround for that problem could be
to add some traits for rational_cast,
e.g. by the following change in rational.hpp:

struct default_cast_tag{};

template<typename I> struct rational_traits
{
  typedef default_cast_tag cast_tag;
};

template <typename T, typename IntType>
inline T rational_cast(const rational<IntType>& src,default_cast_tag)
{
    return static_cast<T>(src.numerator())/src.denominator();
}

template<typename T, typename IntType>
inline T rational_cast(const rational<IntType>& src)
{
  return rational_cast<T>(src,rational_traits<IntType>::cast_tag());
}

Helmut


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