one thing that bugs me about c++

Sean Kelly sean at f4.ca
Thu Dec 13 23:39:34 PST 2007


Neal Becker wrote:
> Sean Kelly wrote:
> 
>> Neal Becker wrote:
>>> In c++,
>>>
>>> template<typename T>
>>> void F (T);
>>>
>>> template<typename T>
>>> void F (std::complex<T>);
>>>
>>> This doesn't work. I want the second overload to be the 'best' match for
>>>
>>> F (std::complex<double>)
>>>
>>> for example, but the standard doesn't agree.
>>>
>>> Never really made sense to me.  What would D do?
>> Seems I need to brush up on my knowledge of template overload
>> resolution, as I'd expect the second overload to be chosen for the
>> reason you provide.  Still, perhaps it isn't truly "more specialized"
>> because in each case a T is being substituted into the one parameter?
>> I'll give the C++ spec a gander on my way home and see if I can come up
>> with anything more enlightening.
>>
>>
> Ouch, I had oversimplified the problem.  The above does compile.  OK, here
> is the _real_ problem:
> --------------------
> #include <complex>
> #include <vector>
> 
> using namespace std;
> 
> template<typename T>
> T mag_sqr1 (T z) { return z * z; }
> 
> template<typename T>
> T mag_sqr1 (complex<T> z) { return real(z)*real(z) + imag(z)*imag(z); }
> 
> template<typename T>
> struct scalar { typedef T type; };
> 
> template<typename T>
> struct scalar<complex<T> > { typedef T type; };
> 
> 
> template<typename T>
> inline vector<typename scalar<T>::type> mag_sqr (vector<T> const& z) {
>   typedef typename scalar<T>::type out_t;
>   vector<out_t> out (z.size());
>   std::transform (z.begin(), z.end(), out.begin(), mag_sqr1<T>);
>   return out;
> }
> 
> int main () {
>   vector<complex<double> > v;
>   mag_sqr (v);
> }
> ------------------
> test1.cc:29:   instantiated from here
> test1.cc:23: error: no matching function for call
> to ‘transform(__gnu_cxx::__normal_iterator<const std::complex<double>*,
> std::vector<std::complex<double>, std::allocator<std::complex<double> > >
>> , __gnu_cxx::__normal_iterator<const std::complex<double>*,
> std::vector<std::complex<double>, std::allocator<std::complex<double> > >
>> , __gnu_cxx::__normal_iterator<double*, std::vector<double,
> std::allocator<double> > >, <unresolved overloaded function type>)’
> 
> But if we change the mag_sqr1 from overloaded functions to functors, this
> compiles fine.  (and change the call to:
> std::transform (z.begin(), z.end(), out.begin(), mag_sqr1<T>())
> )

The error message in VC 8 is a bit more understandable:

     cannot deduce template argument as function argument is ambiguous

If I explicitly specify the in and out iterator types and have it just 
deduce the function type, I also see this as a supplementary message:

     could not deduce template argument for 'overloaded function type'
     from 'overloaded function type'

I'd have to spend some time reasoning this one out, but it looks like 
SFINAE isn't even coming into play in this case.


Sean



More information about the Digitalmars-d mailing list