использование typedef-ed типа в качестве аргумента шаблона класса - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть следующий код:

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;
}

Это, однако, по какой-то причине не компилируется и дает много несвязанных (по моему мнению) и различных ошибок во всех файлах.(Полный их список находится в конце вопроса)

Но если я заменю uint64 в вызове конструктора A на unsigned long long код магическим образомкомпилируется и все ошибки исчезают.Еще более странным является то, что один и тот же код компилируется на некоторых компиляторах, но не на этом.

В чем причина такого поведения?Почему это происходит?И как я могу написать класс для компиляции на разных компиляторах?


Я использую CMake, который использует 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)

Полный список ошибок:

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 голосов
/ 14 декабря 2018

Ваш код действителен (и работает у меня);это ошибка компилятора.Это довольно неприятно!

После небольшого раздвоения на Годболте это выглядит хитроумно, возвращаясь к 4.8 (до этого вы будете бороться за то, чтобы эти NSDMI работали в любом случае!), И если выиспользуйте GCC 6 или выше, с вами все будет в порядке.

...