Search code examples
c++11templatescompiler-errorscudanvcc

CUDA 8.0: Compile Error with Template Friend in Namespace


I noticed that the following code compiles with g++/clang++-3.8 but not with nvcc:

#include <tuple>   // not used, just to make sure that we have c++11
#include <stdio.h>

namespace a {
template<class T>
class X {
  friend T;
};
}

I get the following compile error:

/usr/local/cuda-8.0/bin/nvcc -std=c++11 minimum_cuda_test.cu
nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
minimum_cuda_test.cu:7:10: error: ‘T’ in namespace ‘::’ does not name a type
   friend T;

Interestingly, this works with nvcc:

#include <tuple>   // not used, just to make sure that we have c++11
#include <stdio.h>

template<class T>
class X {
  friend T;
};

Is this a bug in the compiler? I thought nvcc would internally use g++ or clang as a compiler so I am confused why this would work with my local compiler but not with nvcc.


Solution

  • In both cases, the code is being compiled by g++. However, when you pass a .cu file to nvcc, it puts the code through the CUDA C++ front end before passing it to the host compiler. Looking at CUDA 8 with gcc 4.8, I see that the code has been transformed from

    namespace a {
    template<class T>
    class X {
      friend T;
    };
    }
    

    to

    namespace a {
    template< class T>
    class X {
    friend ::T;
    };
    

    You can see that the front end has replaced the templated friend with an equivalent, but with a prepended anonymous namespace, which is breaking the compilation. I'm not a C++ language lawyer, but this would appear to me to be a bug in the CUDA front end. I would suggest reporting it to NVIDIA.