2009-10-13 20 views
5

Tworzę szablon owijający wokół std :: set. Dlaczego pojawia się błąd dla deklaracji funkcji Begin()?błąd powracający std :: set <T> :: iterator w szablonie

template <class T> 
class CSafeSet 
{ 
    public: 
     CSafeSet(); 
     ~CSafeSet(); 

     std::set<T>::iterator Begin(); 

    private: 
     std::set<T> _Set; 
}; 

błąd: typ 'std :: set, std :: podzielnik < _CharT>>' nie pochodzi od typu 'CSafeSet'

+3

Uwaga: przeczytaj o tym, jak używać podkreślników w identyfikatorach. http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier/228797#228797 –

+1

Krótka wersja: "Nie uruchamiaj nazw identyfikatorów za pomocą podkreśleń " – jalf

+0

Wersja długa: podkreślenia poprzedzone wielką literą są zarezerwowane dla kompilatora. Podwójne podkreślenia, a następnie cokolwiek są zarezerwowane również dla kompilatora. – GManNickG

Odpowiedz

17

Spróbuj typename:

template <class T> 
class CSafeSet 
{ 
    public: 
     CSafeSet(); 
     ~CSafeSet(); 

     typename std::set<T>::iterator Begin(); 

    private: 
     std::set<T> _Set; 
}; 

Trzeba TypeName ponieważ jest zależny od szablonu T. Więcej informacji w linku powyżej kodu. Dużo z tych rzeczy jest łatwiejsze, jeśli używasz typedef użytkownika:

template <class T> 
class CSafeSet 
{ 
    public: 
     typedef T value_type; 
     typedef std::set<value_type> container_type; 
     typedef typename container_type::iterator iterator_type; 
     typedef typename container_type::const_iterator const_iterator_type; 

     CSafeSet(); 
     ~CSafeSet(); 

     iterator_type Begin(); 

    private: 
     container_type _Set; 
}; 

Na marginesie, jeśli chcesz być kompletne trzeba zezwolić CSafeSet zrobić to samo jako set could, co oznacza, że ​​przy użyciu niestandardowego comparer a podzielnik:

template <class T, class Compare = std::less<T>, class Allocator = std::allocator<T> > 
class CSafeSet 
{ 
    public: 
     typedef T value_type; 
     typedef Compare compare_type; 
     typedef Allocator allocator_type; 

     typedef std::set<value_type, compare_type, allocator_type> container_type; 
     typedef typename container_type::iterator iterator_type; 
     typedef typename container_type::const_iterator const_iterator_type; 

     // ... 
} 

i ostatni bit radę, jeśli masz zamiar utworzyć otoki wokół klasy, spróbuj wykonać te same konwencje nazewnictwa jak gdzie klasa pochodzi. Oznacza to, że Twój numer Begin() powinien być prawdopodobnie begin() (osobiście uważam, że C przed nazwą klasy jest dziwny, ale to od ciebie zależy:])

+1

Zauważ, że wystąpił błąd w twoim szablonie klasy CSafeSet. Aby zdefiniować typy iteratorów, potrzebujesz również nazwy typu, ponieważ są one również zależne. Przykład: typedef ** nazwa_typu ** typ_konteneru :: iterator typ_ iteratora; Bez tej nazwy nie powinno się kompilować w standardowym kompilatorze zgodnym. Mogę zgadywać, że wypróbowałeś go w Visual Studio (wersja sprzed 2008 roku, kiedy myślę, że zostało to naprawione), które błędnie przyjęło takie linie bez nazwy pliku. –

+0

Wcale nie próbowałem. Dzięki za wskazanie tego, byłem głupi (bardzo często) :) – GManNickG

+0

Wielkie dzięki, GMan. – jackhab

Powiązane problemy