2013-02-08 34 views
5

Mam trudności z zdefiniowaniem i wyspecjalizowaniem funkcji składowej update() klasy wewnętrznej Outer<T1>::Inner, która jest szablonowana na argumencie innym niż typ (wyliczeniowy).Definiowanie wewnętrznego szablonu funkcji członka klasy z argumentem wyliczającym (bez typu)

#include <cstdlib> 

template<typename T1> 
struct Outer 
{ 
    struct Inner 
    { 
     enum Type{ A , B , C }; 

     template<Type T2> 
     void update(); 
    }; 
}; 

// Definition 
template<typename T1> 
template<Outer<T1>::Inner::Type T2> 
void Outer<T1>::Inner::update() 
{ 
} 

// Specialization 
template<typename T1> 
template<Outer<T1>::Inner::A > 
void Outer<T1>::Inner::update() 
{ 
} 

int main() 
{ 
    return EXIT_SUCCESS; 
} 

Dostaję następujący komunikat o błędzie w GCC 4.5.3

prog.cpp:17:28: error: ‘Outer::Inner::Type’ is not a type 
prog.cpp:18:6: error: prototype for ‘void Outer<T1>::Inner::update()’ does not match any in class ‘Outer<T1>::Inner’ 
prog.cpp:11:15: error: candidate is: template<class T1> template<Outer<T1>::Inner::Type T2> void Outer<T1>::Inner::update() 
prog.cpp:24:28: error: ‘Outer::Inner::A’ is not a type 
prog.cpp:25:6: error: prototype for ‘void Outer<T1>::Inner::update()’ does not match any in class ‘Outer<T1>::Inner’ 
prog.cpp:11:15: error: candidate is: template<class T1> template<Outer<T1>::Inner::Type T2> void Outer<T1>::Inner::update() 

BTW, w przeciwieństwie do GCC, Visual Studio 2008 jest w stanie opracować następujące

template<typename T1> 
struct Outer 
{ 
    struct Inner 
    { 
     enum Type{ A , B , C }; 

     template<Type T2> 
     struct Deep; 
    }; 
}; 

template<typename T1> 
template<typename Outer<T1>::Inner::Type T2> 
struct Outer<T1>::Inner::Deep 
{ 
}; 
+0

Muszę przyznać, że to jeden z bardziej humorystycznych komunikatów o błędach z VC2012, które widziałem od jakiegoś czasu: "błąd C2244:" Zewnętrzny :: Wewnętrzny :: aktualizacja ": nie można dopasować definicji funkcji do istniejącej deklaracji, definicja "void Outer :: Inner :: update (void)", istniejące deklaracje: 'void Outer :: Inner :: update (void)' 'Uderzająca różnica między istniejącymi i pożądanymi deklaracjami jest tak oczywista, it = P – WhozCraig

+1

Już miałem zauważyć, że Visual Studio 2008 nie zatwierdza. Czy jest w pobliżu praca? Właściwie to koduję w VS. Używam GCC do sprawdzania zgodności z wymogami poczytalności. – Olumide

+0

@Olumide będzie wystarczające sprawdzić, co robisz? Kompilator najprawdopodobniej zoptymalizuje kontrolę i martwy kod, ponieważ wie, że zawsze będzie to prawda lub fałsz. –

Odpowiedz

4

Przede wszystkim brakuje Ci typename przed Outer<T1>::Inner::Type. Trzeba go mieć, nawet na liście typów template, ponieważ Type jest typem zależnym.

Po drugie, składnia specjalizacji jest nieprawidłowa (typ przechodzi w <> po nazwie funkcji przed nawiasami, a nie w template<>), ale nawet gdyby był poprawny, nie byłby legalny. Musisz specjalizować szablon zewnętrzny, aby móc w pełni wyspecjalizować update, zgodnie z niefortunną regułą dotyczącą specjalizacji jawnego szablonu.

+0

Doh! ... (dzięki.) – Olumide

+2

Dla korzyści nieoświeconych: Jak wyglądałaby "specjalizacja zewnętrznego szablonu" w tym przypadku? – us2012

+1

@ us2012 to byłby po prostu szablon