2015-05-30 8 views
10

Rozważmy następujący kod:non-static inicjalizacji członek dane z nowej ekspresji

#include <map> 

template <typename T> 
struct X { 
    std::map<int, T>* storage = new std::map<int, T>(); 
}; 

int main() { 
    X<int> x; 
} 

To kompiluje na clang 3.6.0, ale nie skompilować na gcc 5.1. Kompilowałoby się jednak, gdyby typ storage był zamiast tego std::vector<T>* (lub po prostu T*).

Jestem całkiem pewien, że to jest błąd kompilatora GCC na części (edit: Poddałem go jako 66344), ale pomyślałem, że pytam się upewnić: czy istnieje jakikolwiek powód, powyższy przykład nie powinienkompilacji ?

gcc błąd kompilacji:

main.cpp:5:51: error: expected ';' at end of member declaration  
    std::map<int, T>* storage = new std::map<int, T>();  
               ^ 

main.cpp:5:51: error: declaration of 'std::map<int, T> X<T>::T'  
main.cpp:3:11: error: shadows template parm 'class T'  
template <typename T>  
     ^

main.cpp:5:52: error: expected unqualified-id before '>' token  
    std::map<int, T>* storage = new std::map<int, T>();  
                ^ 
main.cpp:5:46: error: wrong number of template arguments (1, should be at least 2)  
    std::map<int, T>* storage = new std::map<int, T>();  
              ^

In file included from /usr/local/include/c++/5.1.0/map:61:0,  
       from main.cpp:1:  
/usr/local/include/c++/5.1.0/bits/stl_map.h:96:11: note: provided for 'template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map'  
    class map  
     ^
+0

Tylko dla pewności: używasz 'gcc' lub' g ++ '? Połączyłem to zbyt często ... – atlaste

+0

@atlaste g ++ 4.9.2 też tego nie kompiluje. –

+0

MSVC13 kompiluje go bez błędów. Tak więc wydaje się być błędem – Christophe

Odpowiedz

3

Jest to kolejny przykład problemu opisanego w Core issue 325 (patrz "Uwagi z posiedzenia w sierpniu 2011 roku", które mają bardzo podobny przykład), czyli przecinek w argumencie szablonu lista powoduje niepowodzenie parsowania, gdy kompilator próbuje określić, gdzie znajduje się koniec wyrażenia.

Kwestia nadal jest otwarta, ale konsensus komisji jest taki, że powinna ona działać (nie wiem, co zostanie zmienione, aby była ważna).

Firma Clang zaimplementowała obejście od pewnego czasu (może wstępnie analizować wyrażenie i ponawiać próbę, jeśli się nie powiedzie), a Nathan Sidwell ma tylko un-suspended the relevant G++ bug and assigned it to himself, więc mam nadzieję, że planuje to wkrótce naprawić.

+0

podstawowe wydanie 325 wydaje się być o domyślnych argumentach – sp2danny

+0

@ sp2danny, czytaj dalej, zobacz "Notatki z sierpnia 2011 roku" które mają bardzo podobny przykład –

3

Ciekawe, powinno działać IMO.

Ten skompilować:

#include <map> 

template <typename T> 
struct X { 
    typedef std::map<int, T> mt; 
    mt *storage = new mt(); 
}; 

int main() { 
     X<int> x; 
} 

Widocznie coś pójdzie nie tak z rozbudową szablon argumentu ...

skompilować z:

g++ -o test test.cpp -std=c++11