views:

64

answers:

1

I'm trying to create a template class, and when I define a non-member template function, I get the "No matching function for call to randvec()" error.

I have a template class defined as:

template <class T>
class Vector {
T x, y, z;

public:
//constructors
Vector();
Vector(const T& x, const T& y, const T& z);
Vector(const Vector& u);

//accessors
T getx() const;
T gety() const;
T getz() const;

//mutators
void setx(const T& x);
void sety(const T& y);
void setz(const T& z);

//operations
void operator-();
Vector plus(const Vector& v);
Vector minus(const Vector& v);
Vector cross(const Vector& v);
T dot(const Vector& v);
void times(const T& s);
T length() const;
//Vector<T>& randvec();

//operators
Vector& operator=(const Vector& rhs);
friend std::ostream& operator<< <T>(std::ostream&, const Vector<T>&);
};

and the function in question, which I've defined after all those functions above, is:

//random Vector
template <class T>
Vector<double>& randvec()
{
const int min=-10, max=10;
Vector<double>* r = new Vector<double>;
int randx, randy, randz, temp;

const int bucket_size = RAND_MAX/(max-min +1);

temp = rand();    //voodoo hackery

do randx = (rand()/bucket_size)+min;
while (randx < min || randx > max);
r->setx(randx);

do randy = (rand()/bucket_size)+min;
while (randy < min || randy > max);
r->sety(randy);

do randz = (rand()/bucket_size)+min;
while (randz < min || randz > max);
r->setz(randz);

return *r;
 }

Yet, every time I call it in my main function using a line like:

    Vector<double> a(randvec());

I get that error. However, if I remove the template and define it using 'double' instead of 'T', the call to randvec() works perfectly. Why doesn't it recognize randvec()?

P.S. Don't mind the bit labeled voodoo hackery - this is just a cheap hack so that I can get around another problem I encountered.

+4  A: 

You defined your randvec as a function template, yet no function parameters depend on template parameter T (in fact randvec has no function parameters at all). This immediately means that it is impossible for the compiler to deduce the template argument T from the call to randvec(). You have to specify the template argument T for each call to randvec explicitly, as in

randvec<some_type>()

or, in your context

Vector<double> a( randvec<some_type>() );

This actually rises the question of why you decided to define your randvec as a function template, when nothing in randvec actually depends on the template parameter T. Why?

P.S. Returning a dynamically allocated object by reference... It can be made to work correctly, but it is still a very questionable practice. I don't see your entire code, but I'd guess that your

Vector<double> a( randvec<some_type>() );

leaks Vector<double> object allocated and returned by randvec.

AndreyT
Fantastic. That solved it!
Nick Sweet
@Nick Sweet: *What* exactly solved it? Did you make your `randvec` non-template? Or did you specify some type in `<>`?
AndreyT
I specified a type in <>, as in: vector<double> a(randvec<double>());And yeah, I realize there's a memory leak – I'll look into finding a fix for that – any suggestions?
Nick Sweet