2013-08-13 16 views
7

Kompiluję za pomocą g ++ 4.4.7 (i nie można obecnie przejść wyżej) i przy użyciu przełącznika kompilatora -std=gnu++0x, który powinien umożliwiać składnię trzeciego linia.C++ nie może zainicjować wskaźnika w parze na NULL

typedef std::vector<CI_RecordInfo_Pair> CI_RecordInfo_Vector; 
typedef std::vector<std::pair<std::string, CI_RecordInfo_Vector*> > MgrBlks; 
MgrBlks mgr_n_blks { {"T2M_NAME", NULL} }; // <--- line 59 

Jednak kompilator narzeka następująco:

/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h: In constructor 'std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = const char (&)[9], _U2 = long int, _T1 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = CI_RecordInfo_Vector*]': 
tom.cpp:59: instantiated from here 
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h:90: error: invalid conversion from 'long int' to 'CI_RecordInfo_Vector*' 

Zakładam, że „long int” jest NULL, i że z jakiegoś powodu nie mogę przekonwertować go do wskaźnika. Jeszcze gdzie indziej na mapie struktur, udało mi się skompilować coś w rodzaju:

foo["X"] = { NULL, "bar", 12 }; // first element is a pointer 

Jaka jest różnica?

+4

Czy używa się 'nullptr' zamiast' NULL'? –

+0

Nie jest obsługiwany przez g ++ 4.4. Do 4.6. – Chap

Odpowiedz

14

Kompilator jest poprawna, aby odrzucić tę linię:

MgrBlks mgr_n_blks { {"T2M_NAME", NULL} }; 

w C++ 11 std::pair ma konstruktora szablonów, które ma wszelkie typy argumentów, a następnie konwertuje je do członków:

template<typename X, typename Y> 
    pair(X&& x, Y&& y) 
    : first(std::forward<X>(x)), second(std::forward<Y>(y)) 
    { } 

NULL musi być zdefiniowany jako 0 lub 0L lub coś podobnego, więc dedukcja argumentu szablonu dedukuje argumenty szablonu konstruktora jako const char* i (z GCC) long. Pierwszy typ argumentu można przekształcić na std::string, ale long nie można przekształcić na CI_RecordInfo_Vector*, więc nie można wywołać konstruktora.

Dla drugiego przypadku z mapą struct nie ma argumentów na temat dedukcji, RHS przypisania musi być zamienne do typu struct, w takim przypadku NULL służy do bezpośredniego inicjowania pierwszego elementu struct, a nie pierwszego wydedukowane jako long i inicjujące long, którego nie można przekonwertować na wskaźnik.

Nie używaj NULL w C++ 11, nullptr został stworzony, aby uniknąć dokładnie tych problemów, powinieneś go użyć.

Możliwe obejście byłoby rzucić argument do prawej Typ:

MgrBlks mgr_n_blks { {"T2M_NAME", (CI_RecordInfo_Vector*)NULL} }; 

ale to prostsze i bardziej przejrzyste tylko do korzystania nullptr.

+0

+1 dla określania wartości nullptr zamiast NULL z nowszym C++ –

+0

Jeśli 'NULL' jest zdefiniowane jako' 0', to jest typu 'int', a nie' long'. Wygląda na to, że implementacja definiuje 'NULL' jako' 0L' lub coś podobnego. W g ++ 4.7.2, 'NULL' rozszerza się do' __null', które najwyraźniej ma typ 'long'. –

+0

nullptr nie został dodany przed g ++ 4.6, ale prawidłowe kompilowanie NULL. – Chap

Powiązane problemy