链接器错误与模板化构造函数的未定义引用

时间:2018-03-04 02:54:14

标签: c++

我正在尝试创建模板化函数,它将类型为T的向量作为输入,并将其划分为多个线程。这是通过构造模板化类型为T“VectorWorker”的对象来完成的,迭代器使用迭代器来处理它们需要处理的数据的开头和结尾。

我遇到了链接器错误,我试图传递给VectorWorker构造函数的模板化std :: vec :: const_iterators没有找到相应的构造函数。我的理解是我调用构造函数的参数类型与我定义的构造函数中的参数类型不同。

构造VectorWorkers的模板化函数的相关行是:

/* 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
  }

和VectorWorker的模板化类定义是:

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 */
};

最后,我收到的链接器错误是:

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*> > >)'

编辑:产生错误的MWE: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;
}

1 个答案:

答案 0 :(得分:0)

您声明了VectorWorker的第二个构造函数,但您从未实现它。

#include <vector>
#include <thread>
#include <iostream>

using namespace std;

template <typename T>
class VectorWorker
{
public:
    VectorWorker<T>( typename std::vector<T>::const_iterator begin,  typename std::vector<T>::const_iterator end)
    {
       I NEED IMPLEMENTATION <-------------------------
    }

};

template <typename T>
void makeWorkers(const std::vector<T>& initializerVector)
{
    typename std::vector<T>::const_iterator a,b;
    VectorWorker<T>(a,b);
}

int main()
{
  std::vector<int*> testVec = {new int*, new int*};
  makeWorkers(testVec);
  return 0;
}