使用typedef-ed类型作为类模板参数

时间:2018-12-14 15:17:25

标签: c++ c++11 templates typedef

我有以下代码:

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 ,则代码会神奇地编译并且所有错误都会消失。更奇怪的是,同一代码可以在某些编译器上编译,而不能在这一编译器上编译。

此行为的原因是什么?为什么会这样呢?以及如何编写可在不同编译器上编译的类?


我正在使用使用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 {
       ^

1 个答案:

答案 0 :(得分:1)

您的代码有效(并且对我有用);这是一个编译器错误。真讨厌!

从Godbolt的一个小部分看,它看起来可以回溯到4.8(在您要努力使这些NSDMI正常运行之前,它是困难的!),并且,如果您使用GCC 6或更高版本,则应该没问题。