使用 typedef 类型作为 class 模板参数
using typedef-ed type as class template argument
我有以下代码:
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;
}
但是出于某种原因,这并没有编译,并且在所有文件中给出了很多不相关的(在我看来)和不同的错误。 (他们的完整列表在问题的最后)
但是,如果我将 A 构造函数调用中的 uint64 替换为 unsigned long long,代码会神奇地编译并且所有错误都会消失。更奇怪的是,同样的代码在某些编译器上可以编译,但在这个编译器上却不能。
这种行为的原因是什么?为什么会这样?我怎样才能编写可在不同编译器上编译的 class?
我正在使用使用 C++ 的 CMake:
$ 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)
完整的错误列表:
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 {
^
您的代码有效(对我有效);这是一个编译器错误。真是个讨厌的人!
从 Godbolt 的一点二分法来看,直接回到 4.8 看起来很狡猾(在此之前你将努力让这些 NSDMI 正常工作!),如果你使用 GCC 6 或更高版本,你应该很好。
我有以下代码:
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;
}
但是出于某种原因,这并没有编译,并且在所有文件中给出了很多不相关的(在我看来)和不同的错误。 (他们的完整列表在问题的最后)
但是,如果我将 A 构造函数调用中的 uint64 替换为 unsigned long long,代码会神奇地编译并且所有错误都会消失。更奇怪的是,同样的代码在某些编译器上可以编译,但在这个编译器上却不能。
这种行为的原因是什么?为什么会这样?我怎样才能编写可在不同编译器上编译的 class?
我正在使用使用 C++ 的 CMake:
$ 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)
完整的错误列表:
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 {
^
您的代码有效(对我有效);这是一个编译器错误。真是个讨厌的人!
从 Godbolt 的一点二分法来看,直接回到 4.8 看起来很狡猾(在此之前你将努力让这些 NSDMI 正常工作!),如果你使用 GCC 6 或更高版本,你应该很好。