I have the following preprocessor class, for which I would like to have separate implementations for Real or complex data.
PreProcessor.cuh
#ifndef __PREPROCESSOR_TEST_CUH__
#define __PREPROCESSOR_TEST_CUH__
#include <cuda/std/complex>
#include <iostream>
#define DEFINITION_IN_HEADER 1 // change between definition in src or header file
typedef cuda::std::complex<float> ccfloat;
typedef cuda::std::complex<double> ccdouble;
template <template <class...> class TT, class... Args>
std::true_type is_tt_impl(TT<Args...>);
template <template <class...> class TT>
std::false_type is_tt_impl(...);
// use as is_tt<cuda::std::complex, Q>::value
template <template <class...> class TT, class T>
using is_tt = decltype(is_tt_impl<TT>(std::declval<typename std::decay<T>::type>()));
template <typename Tin, typename Tout>
class PreProcessor
{
public:
// specialization for complex input
template <typename Q = Tin>
typename std::enable_if_t<is_tt<cuda::std::complex, Q>::value, void> run();
// specialization for real input
template <typename Q = Tin>
typename std::enable_if_t<!is_tt<cuda::std::complex, Q>::value, void> run();
};
#if DEFINITION_IN_HEADER
// specialization for complex input
template <typename Tin, typename Tout>
template <typename Q>
typename std::enable_if_t<is_tt<cuda::std::complex, Q>::value, void> PreProcessor<Tin, Tout>::run()
{
std::cout << "COMPLEX template." << std::endl;
}
// specialization for real input
template <typename Tin, typename Tout>
template <typename Q>
typename std::enable_if_t<!is_tt<cuda::std::complex, Q>::value, void> PreProcessor<Tin, Tout>::run()
{
std::cout << "REAL template." << std::endl;
}
#endif
#endif //!__PREPROCESSOR_TEST_CUH__
If I define the respective implementations in the header file, all is good. But when I define them in a source file (i.e. DEFINITION_IN_HEADER =0):
PreProcessor.cu
#include "PreProcessor.cuh"
#if !DEFINITION_IN_HEADER
// specialization for complex input
template <typename Tin, typename Tout>
template <typename Q>
typename std::enable_if_t<is_tt<cuda::std::complex, Q>::value, void> PreProcessor<Tin, Tout>::run()
{
std::cout << "COMPLEX template." << std::endl;
}
// specialization for real input
template <typename Tin, typename Tout>
template <typename Q>
typename std::enable_if_t<!is_tt<cuda::std::complex, Q>::value, void> PreProcessor<Tin, Tout>::run()
{
std::cout << "REAL template." << std::endl;
}
// instantiation
template class PreProcessor<ccfloat, ccfloat>;
template class PreProcessor<int, int>;
#endif
I get the following error:
[build] main.obj : error LNK2019: unresolved external symbol "public: void __cdecl PreProcessor<class cuda::std::__4::complex<float>,class cuda::std::__4::complex<float> >::run<class cuda::std::__4::complex<float> >(void)" (??$run@V?$complex@M@__4@std@cuda@@@?$PreProcessor@V?$complex@M@__4@std@cuda@@V1234@@@QEAAXXZ) referenced in function "public: void __cdecl Processor<class cuda::std::__4::complex<float>,class cuda::std::__4::complex<float> >::run(void)" (?run@?$Processor@V?$complex@M@__4@std@cuda@@V1234@@@QEAAXXZ)
Or, a bit more readable when I use Processor<int, int> Preal;
. What is going on, can I not move SFINAE template speciliazations to src files?
[build] main.obj : error LNK2019: unresolved external symbol "public: void __cdecl PreProcessor<int,int>::run<int>(void)" (??$run@H@?$PreProcessor@HH@@QEAAXXZ) referenced in function "public: void __cdecl Processor<int,int>::run(void)" (?run@?$Processor@HH@@QEAAXXZ)
My main:
main.cu
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <cuda.h>
#include <cuda/std/complex>
#include "PreProcessor_test.cuh"
template <typename Tin, typename Tout>
class Processor
{
public:
PreProcessor<Tin, Tout> *Pp;
Processor() { Pp = new PreProcessor<Tin, Tout>; }
~Processor() { delete Pp; }
void run() { Pp->run(); }
};
int main()
{
Processor<int, int> Preal;
Preal.run();
using ccfloat = cuda::std::complex<float>;
Processor<ccfloat, ccfloat> Pcomplex;
Pcomplex.run();
return 0;
}
Aucun commentaire:
Enregistrer un commentaire