Boost logo

Boost :

From: Hubert Holin (Hubert.Holin_at_[hidden])
Date: 2003-05-12 03:59:13


Somewhere in the E.U., le 12/05/2003

   Bonjour

      I believe, and hope, I got something wrong.

      Updating the special functions library (alongside coding for
prospective new members thereof), I hit a problem, which I can't solve
in a satisfactory manner. It boils down to the following situation:

<CODE>

#include <complex>
#include <iostream>
#include <valarray>

// (1) Plain vanilla templated function

template<typename T>
T f(T x)
{
   ::std::cout << "Plain vanilla templated function" << ::std::endl;
   
   return(x);
}

// (2) Template-template function

template<typename T, template<typename> class U>
U<T> f(U<T> x)
{
   ::std::cout << "Template-template function" << ::std::endl;
   
   return(x);
}

// (3) Valarray function

template<typename T>
::std::valarray<T> f(const ::std::valarray<T> & x)
{
   ::std::cout << "Valarray function" << ::std::endl;
   
   ::std::valarray<T> result = x;
   
   return(result);
}

int main()
{
   double x(1);
   
   f(x);
   
   ::std::complex<double> y(0,1);
   
   f(y);
   
   const ::std::valarray<double> z(3);
   
   f(z);
}

</CODE>

      Let us say that f is sinc. In the current library, I have forms
(1), for the usual floating point types, and (2), for complex,
quaternion and octonions. I wanted to add (3) for valarrays of floating
point types (and later, yet another form for valarrays of complex et
al), along what exists for, say, sin.

      This turns out to be impossible, at least according to my
compiler, which complains about an ambiguity in overload resolution
between (2) and (3) (if I comment out (2) or (3) it all compiles, with
naturally wrong behaviour...). Explicit instantiation (those I have
tried, at least...) does not help.

      I understand that (1) and (2) are unordered (neither is more
specialized than the other). It is also clear that (3) is more
specialized than (1). It is less clear to me that (3) should also be
more specialized than (2).

      One possible, partial, remedie I have in mind would be to remove
(2), add corresponding specializations in the headers for quaternions
and octonions, and add specialization for complex and valarray in sinc's
header (can't modify <complex> or <valarray> as they are standard). But
this is most inelegant, as the code for three specializations is exactly
the same, except for types, and this is precisely the reason for using
(2)! Furthermore, if we want to add new functions that may work on
complex, quaternions and octonions, we would have to modify their
headers for each and every one. That's an appaling lack of
orthogonality! Another approach would be to leave the headers for
quaternions and octonions alone, and stuff sinc's header with lots of
specilizations, most of which really are instanciations of (2), and
that's both inelegant and a possible maintenance problem.

      I welcome any suggestion on that matter (and would most welcome
somebody showing me what I got wrong :-) ).

   Merci

         Hubert Holin


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