简体   繁体   中英

Compile template struct in C++

I have developed a lib of array using C ++ template to deal with many type {int, float, double}. I store the definition and declare of struct and function in file Util.h and Util.cpp. And I call it in the arraySample.cpp. However, I cannot compile the project. The g++ say that undefined reference to printArray

error message

make all 
g++ -O2 -g -Wall -fmessage-length=0   -c -o arraySample.o arraySample.cpp
g++ -O2 -g -Wall -fmessage-length=0   -c -o Util.o Util.cpp
g++ -o arraySample arraySample.o Util.o 
arraySample.o: In function `main':
/home/vtvan/Desktop/workspace/arraySample/arraySample.cpp:15: undefined reference to `int printArray<double>(Array<double>)'
/home/vtvan/Desktop/workspace/arraySample/arraySample.cpp:22: undefined reference to `int printArray<int>(Array<int>)'
collect2: ld returned 1 exit status
make: *** [arraySample] Error 1

Please help me to solve this issue, I have try many times but cannot fix it. It is very strange that when I combine 3 files together, it can work well. So please give me some solutions. I attach here the source code of 3 files for your reference.

Thank you very much and I am looking forward to your reply.

Util.h

#ifndef UTIL_H_
#define UTIL_H_

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <typeinfo>

#define ARRAYMAXNDIMS 3

// multi-dimensional array 
template <typename T>
struct Array {
   T *x;
   int size;
   int nDims;
   int N[ARRAYMAXNDIMS];
};
template <typename T> int printArray(Array<T> A);

#endif /* UTIL_H_ */  

Util.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <typeinfo>

#include "Util.h"

template <typename T> int printArray(Array<T> A) {

  int i = 0, j = 0;
  int k,l;

  std::string typeT = typeid(T).name();

  std::string format("  %9f");

  if (!typeT.compare("i"))
          format = "  %d";

  printf("Array with dimension (%d",A.N[0]);
  k=1;
  while(k<A.nDims && k<ARRAYMAXNDIMS){
    printf(",%d",A.N[k]);
    k++;
  }
  printf(")\n");

  switch (A.nDims) {
  case 1: // print 1D array
    for(k=0;k<A.N[0];k++){ printf("  %9d",A.x[k]);}
    printf("\n");
    return(1);
  case 2: // print 2D array
    for(k=0;k<A.N[0];k++){

      for(l=0;l<A.N[1];l++) {

          printf(format.c_str(),A.x[k+l*A.N[0]]);
      }
      printf("\n");
    }
    return(1);
  case 3: // print last 2 dimensions of a 3D array, where the index of the first dimension is i
    if(i<0 || i>=A.N[0]) {
      printf("index %d is outside the range of indices for the first dimension, i.e. [0:%d]\n",i,A.N[0]-1);
      return(0);
    }
    printf("printing slice (%d,:,:)\n",i);
    for(k=0;k<A.N[1];k++){
//      printf("%5d   ",k);
      for(l=0;l<A.N[2];l++) printf("  %9d",A.x[i+k*A.N[0]+l*A.N[0]*A.N[1]]);
      printf("\n");
    }
    return(1);
  }
}

arraySample.cpp

#include <stdio.h>
#include <stdlib.h>

#include "Util.h"

int main(void) {

    Array<double> a;

    a.nDims = 2; a.N[0] = 2; a.N[1] = 2; a.size = 4;
    a.x = (double *)calloc(a.size,sizeof(double));
    a.x[0] = 1.23; a.x[1] = 2.23; a.x[2] = 3.23; a.x[3] = 5.23;

    printArray(a);

    Array<int>   b;
    b.nDims = 2; b.N[0] = 2; b.N[1] = 2; b.size = 4;
    b.x = (int *)calloc(b.size,sizeof(int));
    b.x[0] = 1; b.x[1] = 2; b.x[2] = 3; b.x[3] = 5;

    printArray(b);

        return 0;
}

You should define your template function printArray in the header file. Just move everything from Util.cpp to Util.h .

Think about it this way. When the compiler is compiling main.cpp , it gets to printArray(a) and then wants to instantiate the printArray template with T as double . However, it can't see the definition of the function, so it can't generate the corresponding code. So to make the function implementation visible to the compiler at this point, you should place it in the header.

An alternative that achieves precisely the same thing is to #include <Util.cpp> at the bottom of Util.h (rather than #include <Util.h> at the top of Util.cpp ). It's pretty common practise to give the template implementation file a .tpp extension instead, however. This makes the relationship a little clearer.

You have already answered your own question in a way. You need to combine the util.cpp code with the util.h file either by cut and pasting the code or by using a #include directive in the util.h file. Then, when you #include the util.h file in arraySample.cpp, you will get the desired effect. For an explanation and some history of this see Chapter 6 of "C++ Templates" by Vandevoorde and Josuttis.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM