0

I'm creating a CUDA/C++ complex numbers/functions library. In particular, I have defined my own implementations of complex types int2_, float2_ and double2_ in ComplexTypes.cuh and ComplexTypes.cu files and I have the following file structure:

Result_Types.cuh - Type traits file - Defines result_type_promotion,

/*************/
/* PROMOTION */
/*************/
template <typename, typename> struct result_type_promotion;
....
template<> struct result_type_promotion< int2_, float2_ >   { typedef float2_ strongest; };
....

/*************/
/* FUNCTIONS */
/*************/

template <typename> struct result_type_root_functions;
....

Operator_Overloads.cuh

template<typename T0, typename T1> __host__ __device__ typename result_type_promotion<T0, T1>::strongest operator+(T0, T1);
....

Operator_Overloads.cu - Overloads of common operations between complex numbers

#include "ComplexTypes.cuh"                                     
#include "Result_Types.cuh"
#include "Operator_Overloads.cuh"
....
__host__ __device__ result_type_promotion<int2_,float2_>::strongest         add(const int2_ a, const float2_ b)  { result_type_promotion<int2_,float2_>::strongest          c; c.c.x = a.c.x+b.c.x; c.c.y = a.c.y+b.c.y; return c; }
....
__host__ __device__ result_type_promotion<int2_,float2_>::strongest operator+(const int2_ a,const float2_ b)  { return add(a,b); }

Function_Overloads.cuh

template<typename T0> typename result_type_root_functions<T0>::root_functions                   Asinh(T0);

Function_Overloads.cu - Overloads of functions on complex numbers

#include "ComplexTypes.cuh"                                     
#include "Result_Types.cuh"
#include "Operator_Overloads.cuh"

__host__ __device__ result_type_root_functions<int>::root_functions         Asinh(const int a)              { return asinh((float)a); }
....

The above files, except for the type traits file which is dealt with as an include file, are compiled on the command line using nvcc and cl to form a .lib file.

Unfortunately, when I compile the main function which includes

#include "ComplexTypes.cuh"
#include "Result_Types.cuh"
#include "Operator_Overloads.cuh"
#include "Function_Overloads.cuh"

I have linkage errors of the type

Error   247 error : Undefined reference to '_ZplIN2BB5int2_ENS0_7float2_EEN21result_type_promotionIT_T0_E9strongestES4_S5_' in '...Test.lib'

Please, note that:

  1. Only the complex types int2_, float2_ and double2_ are in a BB namespace, but I'm adding using namespace BB; in all the definition files;
  2. The problem arises when I'm using + in the Function_Overloads.cu file; if I'm not using +, then no problem arises;
  3. I (surprisingly) can use + in the main function without receiving any linkage error.

Any idea to solve this problem?

Thanks.

EDIT

Following billz suggestions, I have solved the problem by adding explicit instantiations in the Function_Overloads.cu file, like

__host__ __device__ result_type_promotion<int,int2_>::strongest operator+(const int a,const int2_ b);
....
Vitality
  • 20,705
  • 4
  • 108
  • 146

1 Answers1

1

_ZplIN2BB5int2_ENS0_7float2_EEN21result_type_promotionIT_T0_E9strongestES4_S5_

decoded by c++filt becomes:

result_type_promotion<BB::int2_, BB::float2_>::strongest operator+<BB::int2_, BB::float2_>(BB::int2_, BB::float2_)

Which means your compiler can't find function definition, you need to implement it in header file.

billz
  • 44,644
  • 9
  • 83
  • 100
  • Thank you very much for pointing out that as well as the use of `c++filt`. What is not very clear to me is why, once created the static library, can I use the `+` operator in the `main` function but I have no visibility of such an overload inside a function defined in `Function_Overloads.cu`. Could you suggest any test that I can make to solve this problem (provided that this problem _has_ a solution :-) )? – Vitality Oct 09 '13 at 10:07
  • this link may help: http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – billz Oct 09 '13 at 10:12
  • I have added explicit instantiations (not implementations) in the `Function_Overloads.cu` file and this solved the problem. Following your link, I understand that in my original version in the compilation unit of `Function_Overloads.cu` there was no instantiation to be subsequently linked and I also understand why now explicit instantiations solve the problem. However, I do not understand why in the `main` function everything works without explicit instantiations. – Vitality Oct 09 '13 at 14:59
  • By the way, there is an online demangler: [c++filtjs](http://pear.warosu.org/c++filtjs/). – Vitality Oct 09 '13 at 19:52