1

I have the following program. It is object oriented, having a structure 'array' (I have to use structure defined by me, so vector.h doesn't count) where I store some objects. The Class functions and the structure work just fine in M.cpp (main) but when I try to call them from controller.cpp I get a reference error.

ListStruct.h:

template <class T>
struct Array{
    int days;
    T * M;

    Array( int size ) : days(size), M(new T[size])
    {
    }
    ~Array()
    {
       delete[] M;
    }
};

void currentDay();

template <class T>
void add(int,int,Array<T> &);

template <class T>
void dummyData(Array<T> &);

ListStruct.cpp

#include <stdlib.h>
#include <iostream>
#include <ctime>

#include "ListStruc.h"
#include "Expe.h"

using namespace std;

int currDay;

void currentDay(){
    time_t t = time(0);   // get time now
    struct tm * now = localtime( & t );
    ::currDay = now->tm_mon + 1;
}

void add(int cant, int type,Array <Expe> &A){
    //Adds to current day the amount to a specific type
    int newVal;
    newVal = A.M[currDay].getObj(type);
    newVal += cant;
    A.M[currDay].editObj(type,newVal);

}

void dummyData(Array <Expe> &A){
    for(int i=0; i<31; i++){
        A.M[i].Expe::setObj((i*3),(i*1),(i*6),(i*2),(i*4),(i*5));
    }
}

M.cpp - main function on the program:

#include <iostream>

#include "Expe.h"
#include "ListStruc.h"
#include "Controller.h"

using namespace std;
int main(){
//Main function of the program. no pre/ post condition.

Array <Expe> A(31);   // Work space
Array <Expe> B(31);   // Backup space

cout<<&A; // testing for allocation
cout<<&B;

Expe a;
a.setObj(5,5,5,5,5,5); // checking class functions
a.printObj();

A.M[1]=a;
A.M[1].printObj();

//check dummy FOR-, WORKS!
for(int i=0; i<31; i++){
    A.M[i].Expe::setObj((i*3),(i*1),(i*6),(i*2),(i*4),(i*5));
}

a.editObj(3,100);
a.printObj();        // check objects calling, WORKS!
cout<<"Obj A.[10]:";
A.M[10].printObj();
cout<<endl<<"Obj A.[29]:";
A.M[29].printObj();

    dummyData(A);  ///////ERROR/////////

ERROR:

D:\c++\Begin\Lab3-5_OOP\Debug/../M.cpp:44: undefined reference to `void dummyData<Expe>(Array<Expe>&)'

I tried everything that I could think of... surfed the internet and still couldn't find the reason for that reference error.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Bogdan Maier
  • 663
  • 2
  • 13
  • 19

2 Answers2

1

Looks like the version of dummyData you've provided in ListStruct.cpp is not considered as a full specialization of a templated version. So, compiler is unable to find it. You should define it as a template<> void dummyData<Expe>(Array<Expe>&).

parallelgeek
  • 438
  • 2
  • 11
1

You are declaring function templates add and dummyData, but defining non-templates.

If you only need these functions to work on Array<Expe> rather than on generic arrays, then change the declarations to non-templates:

class Expe;
void add(int,int,Array<Expe> &);
void dummyData(Array<Expe> &);

If they need to be generic, then you'll have to move the definitions into the header file; templates usually need the definition to be available in every source file that uses them. However, your functions appear to be working specifically with Expe, so I don't think they do want to be templates.

Also, your Array type is breaking the Rule of Three, making it very dangerous to use. Why don't you use std::vector to manage the dynamic array safely?

UPDATE: You say you want to see how to do this while keeping it a template. To do that, you'll need an explicit specialisation for Expe. That would look something like this:

template <> void dummyData(Array<Expe> &) {
    // your Expe version goes here
}

I'm not 100% sure whether or not you'd also need to declare the specialisation in the header file; it's a long time since I've done anything this weird, so I'm not quite sure of the details. Certainly, if you implement the generic version, then you will have to declare this specialisation; otherwise the generic version will be chosen instead. In any event, it's simpler just to overload the function for Array<Expe>.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • As far as I know, if you have a full specialization of a templated function, you may write it by hand and hide it inside .cpp file. Am I wrong? :) – parallelgeek Apr 22 '12 at 14:03
  • And lets suppose i want ti to be tempelt based what would be the way? could you show me an example? – Bogdan Maier Apr 22 '12 at 14:04
  • @parallelgeek: Yes, you could do that, but there's no point; overloading gives you the same result more simply. – Mike Seymour Apr 22 '12 at 14:05
  • i dont use because i`m student and we have a lab assigment which includes getting familiar with tempaltes, structures and classes... so vector.h is foebidden – Bogdan Maier Apr 22 '12 at 14:10
  • 1
    You could write a specific implementation by hand (for specific type parameters such as Expe in this case) and all you have to do is point that this definition is a templated function by writing `template<> void dummyData(Array&) { // The body here }`. In case you need a generic version too, you should place it in a header file, because this version will be used for generating those specializations which are not written by hand. – parallelgeek Apr 22 '12 at 14:11
  • Thank you Mike Saymore :) rally handy your answere, sorry for all the questions :P – Bogdan Maier Apr 22 '12 at 14:55