Reputation: 2275
I have the following code:
typedef unsigned long long uint64;
template<typename K, typename V>
class A {
K a;
V b;
public:
A() {}
};
class B {
private:
A<uint64, uint64>* a = new A<uint64, uint64>(); // does not compile
A<uint64, uint64>* b = new A<unsigned long long, unsigned long long>(); // does compile
};
int main() {
new B();
return 0;
}
This however for some reason does not compile and gives a lot of unrelated (in my opinion) and different errors across all the files. (The complete list of them is at the end of the question)
But if I replace the uint64 in the A constructor invocation with unsigned long long the code magically compiles and all the errors disappear. What is even more strange is that the same code compiles on some compilers but not on this one.
What is the reason for this behaviour? Why is this happening? And how can I write the class to be compilable on different compilers?
I am using CMake which is using c++:
$ c++ -v
Using built-in specs.
COLLECT_GCC=c++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
Complete list of errors:
main.cpp:16:42: error: expected ‘;’ at end of member declaration
A<uint64, uint64>* a = new A<uint64, uint64>(); // does not compile
^
main.cpp:16:42: error: declaration of ‘A<long long unsigned int, long long unsigned int> B::uint64’ [-fpermissive]
main.cpp:3:28: error: changes meaning of ‘uint64’ from ‘typedef long long unsigned int uint64’ [-fpermissive]
typedef unsigned long long uint64;
^
main.cpp:16:48: error: expected unqualified-id before ‘>’ token
A<uint64, uint64>* a = new A<uint64, uint64>(); // does not compile
^
main.cpp:16:34: error: wrong number of template arguments (1, should be 2)
A<uint64, uint64>* a = new A<uint64, uint64>(); // does not compile
^
main.cpp:6:7: error: provided for ‘template<class K, class V> class A’
class A {
^
Upvotes: 2
Views: 65
Reputation: 385114
Your code is valid (and works for me); this is a compiler bug. Quite a nasty one at that!
From a little bisection on Godbolt, it looks dodgy going right back to 4.8 (prior to that you're going to struggle to get those NSDMIs working anyway!), and if you use GCC 6 or higher you should be fine.
Upvotes: 1