Template specialization for template types

I'm programming a template class Vector in order to perform algebraic operations:
1
2
3
4
5
6
7
8
9
10
#include <ccomplex>
template <class T>
class Vector{
  //...
public:
  T operator*(const Vector<T> &v); //Dot product
};
template <class T> T Vector<T>::operator*(const Vector<T> &v){
  // Calculating dot product...
}


This woks fine for real numers (i.e. int, long, float, double,...). But complex numers (complex<float>, complex<double>,...) would need different a function (see http://en.wikipedia.org/wiki/Dot_product#Complex_vectors). I thought about template specialization, something like:
1
2
3
template <class T> complex<T> Vector<complex<T> >::operator*(const Vector<complex<T> > &v){
  //Calculating complex dot product...
}


When I try this code, I get a compiler error (with gcc):
Invalid use of incomplete type 'class Vector<std::complex<_Tp> >'


What should I do to avoid this compiler error and achieve what I want to do?

Thanks in advance!
I think it is confusing the compiler because it will not be able
to determine T.
You are using the term Vector<complex<T> > as the class name
but what is T - it cant be complex<T> because complex<T> is not
a concrete class - so T is indeterminate so complex<T> cannot be instantiated.


You can just specialise for each complex class you want
for example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <complex>

template <class T>
class Vector{
  //...
public:
  T operator*( Vector<T> &v); //Dot product
};
template <class T>
 T Vector<T>::operator*( Vector<T> &v)
 {
  // Calculating dot product...
  
  //return whatever
}

//specialisation for complex<double>
template<>
complex<double> Vector<complex <double> >::operator*( Vector <complex<double> > &v)
{
    
   //Do stuff 
    //return whatever
}

int main()
{
      
    Vector < complex<double>  > xx;
    
    xx*xx;
}

Last edited on
template <class T> complex<T> Vector<complex<T> >
What is this doing?
1
2
3
template <class T>
    complex<T>
        Vector<complex<T> >

What do you expect this do to?


Also, why would complex numbers need a specialization? Doesn't the complex class overload enough operators to be supported by your class already?
Last edited on
guestgulkan:
You can just specialise for each complex class you want

Yes, of course that would work. But that way, I've got to do a specialization for complex<double>, other for complex<float>, other for complex<int>, and so on... That is totally opposed to the spirit of templates. My question was if there is a way to do it with only one specialization.

L B:
What is this doing?
Well, the first complex<T> is supposed to be the return type, Vector<complex<T> >:: the scope (the operator is a member function), and template<class T> is declaring as a template, because I want the function to work on all the complex<T> types. I already now that is not the right code, I'm just asking how to fix it.

why would complex numbers need a specialization?

Complex numbers need a specialization for a mathematical reason, not for a overloading one: real dot product of two vectors v = (v1, ... vn) and w = (w1, ... wn) is the sum of the terms v1·w1, while complex dot product is the sum of the terms v1·(w1)* (where * means complex conjugation). And I can't overload conjugation because is only a function defined for complex<>, not for int, float or double
OK I see.

Now, here are a couple points:
-You need to always define template functions inline, even member functions of a templated class.
-You need not specialize the entire class, only the functions that need slightly different behavior.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <complex>

template <class T>
class Vector{
  //...
public:
  T operator*( Vector<T> &v); //Dot product
};
template <class T>
 T Vector<T>::operator*( Vector<T> &v)
 {
  // Calculating dot product...
  
  T t;
  return t;
}

//Partial Class specialisation for complex class - should do the trick?
//What does the guts of the vector class look like I wonder))
template <class T>
class Vector <complex <T> >{
  //...
public:
 complex <T>  operator*( Vector<complex <T> > &v); //Dot product

//Other specialisations to cope with complex<T> type as required.

};

template<class T>
complex<T> Vector<complex <T> >::operator*( Vector <complex<T> > &v)
{
    
   //Do stuff 
    //return whatever
    complex<T> tt; //Test to prove
    return tt;//Test to prove
}


int main()
{
      //Test 1
     Vector<complex<float> > vcf;
     vcf*vcf;
     
     //Test 2
     Vector <complex<double> > vcd;
     vcd*vcd;
     
}


((basically you will be making an additional Vector class to deal with the
complex< T> case - after all that is what partial specialization boils down to)
Last edited on
See if you understand this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <complex>

template <class T>
struct Vector
{
	T operator*(const Vector &v) const
	{
		std::cout << "Dot Product for Real Types" << std::endl;
		T t;
		return t;
	}
};
template<>
template<typename T>
struct Vector<std::complex<T> >
{
	T operator*(const Vector &v) const
	{
		std::cout << "Dot Product for Complex Types" << std::endl;
		T t;
		return t;
	}
};

int main()
{
    Vector<int> vcf;
    vcf*vcf;

    Vector <std::complex<double> > vcd;
    vcd*vcd;
}
The reason I replied even though the gulkan guest gave an asnwer was because his was incorrect and it did not correctly inline functions.
Last edited on
> My question was if there is a way to do it with only one specialization.

You don't need to either fully or partially specialize the entire Vector<> class if a different implementation is required just for one operation: the vector dot product operator*()

However, the IS does not permit explicit specialization of a member function of a class at class scope. The simplest work around in this case is to write the vector dot product as a free function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <ccomplex>

template < typename T > class Vector ;
template < typename T > T operator* ( const Vector<T> &a, const Vector<T>& b ) ;

template < typename T > class Vector
{
  //...

  friend T operator* <> ( const Vector<T>& a, const Vector<T>& b ) ; 
};

template < typename T > T operator* ( const Vector<T>& a, const Vector<T>& b ) // generalization
{
    // ...
}

template < typename T > // partial specialization for std::complex<T>
std::complex<T> operator* ( const Vector< std::complex<T>& > &a, const Vector<std::complex<T> >& b )
{
    // ...
}
And I can't overload conjugation because is only a function defined for complex<>, not for int, float or double

Just in case I've tried it, and it does work!! So, I don't really need function or class specialization at all. The same function works fine with both real numbers (conj() // returns simply the same number ) and complex numbers (conj() //returns the complex conjugate )

Anyway, thanks for your help. Now I've learned how to do that when the overloading trick doesn't work.
Topic archived. No new replies allowed.