I am attempting to create templated function, which takes as input a vector of type T and divides it among several threads. This is done by constructing objects of templated type T "VectorWorker" with iterators to the beginning and end of the data they need to process.
I am running into a linker error, where the templated std::vec::const_iterators I am attempting to pass to the VectorWorker constructor is not finding a corresponding constructor. My understanding is that the types of the parameters I am calling the constructor with, differs from the types of the parameters in the constructor I have defined.
The relevant lines of the templated function which constructs the VectorWorkers are:
/* function to create initial worker that spawns more workers*/
template <typename T>
void makeWorkers(const std::vector<T>& initializerVector)
{
int quotient = initializerVector.size()/NUMTHREADS; // divide by number of threads
int remainder = initializerVector.size()%NUMTHREADS; //find remainder after division which will have to be distributed
//store the iterators for all our workers in a 2 X NUMTHREADS matrix. Where first column is each workers beginning iterator
//and second column is each worker's ending iterator
typename std::vector<T>::const_iterator itArray[NUMTHREADS][2];
VectorWorker<T> workerArray [NUMTHREADS]; //instantiate array to hold all workers
std::thread threadArray[NUMTHREADS]; //instantiate array to hold threads which will run worker's work() method
//The first "remainder" distances should be quotient+1, the remaining should just be quotient to yield
// remainder(quotient+1)+(N-remainder)(quotient) = N*Quotient+remainder
itArray[0][0] = initializerVector.begin();
if(remainder ==0)
{
remainder=NUMTHREADS; //to prevent division by zero
itArray[0][1] = initializerVector.cbegin()+quotient-1; //limit distance between first two iterators to quotient
}
else
itArray[0][1] = initializerVector.cbegin()+quotient-1; //The distance between first two iterators should be quotient+1
for (int i=1; i<NUMTHREADS; ++i)
{
itArray[i][0]=itArray[i-1][0]+quotient+1-(int)(i<remainder);
itArray[i][1]=itArray[i-1][1]+quotient+1-(int)(i<remainder);
}
/*
typename std::vector<T>::const_iterator begin;
begin = itArray[0][0];
*/
// construct all worker objects
for( int i=0; i<NUMTHREADS; ++i)
{
workerArray[i]=VectorWorker<T>(itArray[i][0],itArray[i][1]); //copy assignment into default initialized array objects
}
and the templated class definition for VectorWorker is:
template <typename T>
class VectorWorker
{
public:
VectorWorker<T>() = default;
VectorWorker<T>( typename std::vector<T>::const_iterator begin, typename std::vector<T>::const_iterator end);
void Work() const
{
std::cout<<"I worked"<<std::endl;
return;
};
private:
typename std::vector<T>::const_iterator beginIt; /* Stores value of left iterator that defines data for this worker */
typename std::vector<T>::const_iterator endIt; /* Stores value of right iterator that defines data for this worker */
};
Finally, the linker error I am receiving is:
CMakeFiles/P2.dir/fft2d.cc.o: In function `void makeWorkers<Complex*>(std::vector<Complex*, std::allocator<Complex*> > const&)':
undefined reference to `VectorWorker<Complex*>::VectorWorker(__gnu_cxx::__normal_iterator<Complex* const*, std::vector<Complex*, std::allocator<Complex*> > >, __gnu_cxx::__normal_iterator<Complex* const*, std::vector<Complex*, std::allocator<Complex*> > >)'
EDIT: MWE that produces the error on: https://www.onlinegdb.com/online_c++_compiler
#include <vector>
#include <thread>
#define NUMTHREADS 4
template <typename T>
class VectorWorker
{
public:
VectorWorker<T>() = default;
VectorWorker<T>( typename std::vector<T>::const_iterator begin, typename std::vector<T>::const_iterator end);
void Work() const
{
std::cout<<"I worked"<<std::endl;
return;
};
private:
typename std::vector<T>::const_iterator beginIt; /* Stores value of left iterator that defines data for this worker */
typename std::vector<T>::const_iterator endIt; /* Stores value of right iterator that defines data for this worker */
};
using namespace std;
/* function to create initial worker that spawns more workers*/
template <typename T>
void makeWorkers(const std::vector<T>& initializerVector)
{
int quotient = initializerVector.size()/NUMTHREADS; // divide by number of threads
int remainder = initializerVector.size()%NUMTHREADS; //find remainder after division which will have to be distributed
//store the iterators for all our workers in a 2 X NUMTHREADS matrix. Where first column is each workers beginning iterator
//and second column is each worker's ending iterator
typename std::vector<T>::const_iterator itArray[NUMTHREADS][2];
VectorWorker<T> workerArray [NUMTHREADS]; //instantiate array to hold all workers
std::thread threadArray[NUMTHREADS]; //instantiate array to hold threads which will run worker's work() method
//The first "remainder" distances should be quotient+1, the remaining should just be quotient to yield
// remainder(quotient+1)+(N-remainder)(quotient) = N*Quotient+remainder
itArray[0][0] = initializerVector.begin();
if(remainder ==0)
{
remainder=NUMTHREADS; //to prevent division by zero
itArray[0][1] = initializerVector.cbegin()+quotient-1; //limit distance between first two iterators to quotient
}
else
itArray[0][1] = initializerVector.cbegin()+quotient-1; //The distance between first two iterators should be quotient+1
for (int i=1; i<NUMTHREADS; ++i)
{
itArray[i][0]=itArray[i-1][0]+quotient+1-(int)(i<remainder);
itArray[i][1]=itArray[i-1][1]+quotient+1-(int)(i<remainder);
}
/*
typename std::vector<T>::const_iterator begin;
begin = itArray[0][0];
*/
// construct all worker objects
for( int i=0; i<NUMTHREADS; ++i)
{
workerArray[i]=VectorWorker<T>(itArray[i][0],itArray[i][1]); //copy assignment into default initialized array objects
}
return;
}
int main()
{
cout<<"Hello World";
std::vector<int*> testVec = {new int*, new int*};
makeWorkers(testVec);
return 0;
}