Program compiles in gcc5 but not with nvcc

What follows is a bit of code extracted from my larger application, therefore I will not explain the context, so unless its invalid code, which I don’t think it is, please don’t ask “why” as its probably a distraction from the problem. Thank you.

The following code fragment compiles successfully in gcc-5 but not with nvcc, which, as far as I understand invokes gcc-5 in order to compile non-device code. Why?

template<typename T> 
struct Wrapper;

template<typename ...Args> 
struct Wrapper<void(Args...)>
{
};

template<typename T>
void test( int )
{
}

extern template struct Wrapper<decltype(test<float>)>;

int main()
{
}
nvcc -ccbin g++-5 -std=c++11 -g -std=c++11 -m64 -gencode arch=compute_30,code=sm_30 -o Test Test.cu

yields the error

Test.cu: error: explicit instantiation of ‘struct Wrapper<void (&)(int)>’ before definition of template
 extern template struct Wrapper<decltype(test<float>)>;

Whereas compiling with gcc thusly (note the contents of Test.cpp are identical to Test.cu)

g++-5 -std=c++11 Test.cpp

succeeds.

What’s going on here? Does nvcc attempt to parse or compile C++ code?

Yes, nvcc does various kinds of preprocessing, even to host or host-only code that is in a .cu file. You can get an idea of what nvcc does “under the hood” by using some compile options like --keep or --verbose, which you can read about in the nvcc manual. You can avoid this by passing the file with a .cpp extension, which avoids the preprocessing step, but of course that isn’t what you’re after here (probably).

This appears to be some sort of defect in nvcc. My suggestion would be to file a bug at http://developer.nvidia.com

I’ve actually just done that, -verbose shows that the problem is at this step of the compilation process

$ g++-5 -std=c++11 -c -x c++ -fpreprocessed -m64 -g -gdwarf-2 -o "/tmp/tmpxft_00002474_00000000-16_Test.o" "/tmp/tmpxft_00002474_00000000-15_Test.ii" 
Test.cu: error: explicit instantiation of ‘struct Wrapper<void (&)(int)>’ before definition of template
 template struct Wrapper<decltype(test<float>)>;

I’ll file a bug report right away.