2

I am trying to pass a function pointer in to a constructor of a class. However, when I try to compile the code, I am getting an error. The code and error are :

quickfind.h

#ifndef QUICKFIND_H
#define QUICKFIND_H
#endif // QUICKFIND_H

template <class T>
class QuickFind
{
private:
    int size;
    int *array;
    int (*giveIndex)(const void *a);
public:
    QuickFind<T>(int n,int (*ptr)(const void *));
    void connect (const T* u,const T* v);
    bool isConnected(const T* u,const T* v);
};

Constructor definition in file quickfind.cpp

template <class T>
QuickFind<T>::QuickFind(int n,int (*ptr)(const void *))
{
    size=n;
    array=new int[n];
    giveIndex=ptr;
    for(int i=0;i<n;i++)
    {
        array[i]=i;
    }
}

In my main function file :

int giveIndex (const void *ptr)
{
    temp *tptr=(temp*)ptr;
    return tptr->getA();
}

int main()
{
     QuickFind<temp> *qf=new QuickFind<temp>(10,giveIndex);
}

Here, I am getting 'undefined reference to QuickFind<temp>::QuickFind(int, int (*)(void const*))' error. I am not able to figure out the problem...please help.

Nik Bougalis
  • 10,495
  • 1
  • 21
  • 37
tigerden
  • 728
  • 2
  • 11
  • 28
  • 1
    Check out [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) for details. Also, that include guard in the header file is plain weird... – Nik Bougalis Apr 06 '13 at 15:11

3 Answers3

2

One thing wrong, you don't need the on the constructor:

template <class T>
class QuickFind
{
private:
    int size;
    int *array;
    int (*giveIndex)(const void *a);
public:
    QuickFind(int n,int (*ptr)(const void *));  /// <---- here, no <T>
    void connect (const T* u,const T* v);
    bool isConnected(const T* u,const T* v);
};

In your case, the class it templated, but this function isn't. And, template functions must be defined in the header file so that the file that includes them can see the code and substitute the parameter types.

Scott Langham
  • 58,735
  • 39
  • 131
  • 204
  • Read my comment. You cannot have template implementations in .cpp files. – Nik Bougalis Apr 06 '13 at 15:18
  • I added #include "quickfind.cpp" in the end of quickfind.h. and then compiled all the header and .cpp files one by one by g++. Finally while compiling as `g++ quickfind.o tempclass.o tempmain.o -o tempmain.exe` is giving the same error. – tigerden Apr 06 '13 at 15:23
1

Put all of the following in one CPP file to see it work. As noted in other comments you must, for templated classes, put the entire definition in the header file. Do not separate the function declaration from its definitions into a separate CPP file. In this case having the entire implementation in the one CPP file serves the same purpose.

I have made some changes to your code to make it typesafe, memory leak safe and more exception safe. For example I replaced your dynamically allocated array with std::vector. std::vector has all the features you need but manages the memory for you and will be cleaned up when your class goes out of scope.

#include <vector>
#include <iostream>
#include <functional>

template <typename T>
class QuickFind
{
private:
    std::vector<int> data;
std::function<int (const T&)> func;
public:
    QuickFind(int n, std::function<int (const T&)> f) : data(n), func(f)
    {
        int i = 0;
        for(auto it = data.begin(); it != data.end(); ++it)
            data[i]=i++;
    }

    void connect (const T& u, const T& v)
    {
        std::cout << func(u) << "\n";
        std::cout << func(v) << "\n";
    }
    bool isConnected(const T* u,const T* v);
};

class temp
{
    int val;
public:
    temp(int i) : val(i)
    {}

    int getA() const
    {
        return val;
    }
};

int giveIndex (const temp &t)
{
    return t.getA();
}

int main()
{
     temp t1(5), t2(10);

     QuickFind<temp> qf1(10,giveIndex);
     qf1.connect(t1, t2);

     // this example uses a lambda as the callback
 auto giveIndex2 = [](const temp& t) { return t.getA(); };
 QuickFind<temp> qf2(20, giveIndex2);
 qf2.connect(t1, t2);
}
Peter R
  • 2,865
  • 18
  • 19
0

The compiler wants to know objects of which types will be instantiated from a template class at the time of compilation of template class methods. So, there may arise compile-time or link-time errors. This explains more about various errors and their causes.

Adding #include "quickfind.cpp" in the end of the header file worked in my case after some efforts.

tigerden
  • 728
  • 2
  • 11
  • 28