     cudaStream_t stream)
 {
   // using c++11 std::is_same here
-  const char* type;
-  if (std::is_same<IndexType, unsigned long>::value)
-    type = "unsigned long";
-  else if(std::is_same<IndexType, unsigned int>::value)
-    type = "unsigned int";
+  const char* index_type = getTypeString<IndexType>();
+  const char* ta_type = getTypeString<Ta>();
+  const char* tb_type = getTypeString<Tb>();
 
   char src[2048];
-  sprintf(src, instanciate_apply2, type, op, A, B);
+  sprintf(src, instanciate_apply2, ta_type, tb_type, index_type, op, A, B);
   const char *headers[] = {apply_header};
   const char *includeNames[] = {"header.h"};
 
   PTXPtr ptx;
-  Apply2Hash hash(op, type, A, B);
-  auto found_hash = apply2cache.find(hash);
-  if(found_hash == apply2cache.end())
+  ApplyHash hash(op, std::string(ta_type)+"_"+tb_type, index_type, A, B);
+  auto found_hash = applycache.find(hash);
+  if(found_hash == applycache.end())
   {
     ptx = PTXPtr(new PTX());
     compilePTX(src, headers, includeNames, *ptx);
-    apply2cache.emplace(hash, ptx);
+    applycache.emplace(hash, ptx);
   }
   else
     ptx = found_hash->second;

  launch(ptx->data(), "kernel", args, grid, block, (CUstream)stream);
}

/*
// Example op: 'x = x*y'
const char* instanciate_apply2 = "                                      \n\
#define TYPE %s								\n\
#include <header.h>                                                     \n\
struct Op {                                                             \n\
  __device__ __forceinline__						\n\
  void operator()(float* a, float* b) {      				\n\
    float& x = *a;                                                      \n\
    float& y = *b;							\n\
    %s;                                                                 \n\
  }                                                                     \n\
};                                                                      \n\
extern \"C\" __global__                                                 \n\
void kernel(TensorInfo<TYPE> a, TensorInfo<TYPE> b, TYPE totalElements) \n\
{                                                                       \n\
  Op op;                                                                \n\
  THCudaTensor_pointwiseApply2<Op,TYPE,%d,%d>				\n\
  			(a, b, totalElements, op);			\n\
}                                                                       \n\
";

template <typename IndexType>
void THCudaTensor_pointwiseApply2RTC(
    TensorInfo<IndexType> aInfo,
    TensorInfo<IndexType> bInfo,
    const char* apply_header,
    const char* op,
    IndexType totalElements,

typedef %s Ta;                                                          \n\
typedef %s IndexType; 							\n\
struct Op {                                                             \n\
    __device__ __forceinline__ void operator()(Ta* __v) {                \n\
    Ta& x = *__v;                                                      \n\
    %s;                                                                 \n\
  }                                                                     \n\
};                                                                      \n\
