## digitalmars.D - one thing that bugs me about c++

- Neal Becker (9/9) Dec 13 2007 In c++,
- Walter Bright (4/19) Dec 13 2007 void F(T)(T t) { ... }
- Sean Kelly (8/23) Dec 13 2007 Seems I need to brush up on my knowledge of template overload
- Neal Becker (37/64) Dec 13 2007 Ouch, I had oversimplified the problem. The above does compile. OK, he...
- Walter Bright (2/9) Dec 13 2007 That just makes my eyeballs hurt.
- guslay (5/36) Dec 13 2007 The instantiation capability within std::transform appears to be the lim...
- Sean Kelly (10/83) Dec 13 2007 The error message in VC 8 is a bit more understandable:

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?

Dec 13 2007

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?void F(T)(T t) { ... } void F(T:cdouble)(T t) { ... } should do it.

Dec 13 2007

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. Sean

Dec 13 2007

Sean Kelly wrote:Neal Becker wrote: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>()) )

Dec 13 2007

Neal Becker wrote: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; }That just makes my eyeballs hurt.

Dec 13 2007

Neal Becker Wrote:-------------------- #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); }The instantiation capability within std::transform appears to be the limitation. Who knows why. If you do it in two steps, by first defining a function pointer, it works fine for complex and double. out_t (*ptrF)(T) = &mag_sqr1; std::transform (z.begin(), z.end(), out.begin(), ptrF ); I will leave the implementation in D to someone else, but I bet it would look better.

Dec 13 2007

Neal Becker wrote:Sean Kelly wrote: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. SeanNeal Becker wrote: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>()) )

Dec 13 2007