2014-08-31 16 views
6

Z poniższego fragmentu kodu pojawia się ostrzeżenie:ostrzeżenie: specjalizacja szablonu w innej przestrzeni nazw

warning: specialization of ‘template<class _Iterator> struct std::iterator_traits’ in different namespace [-fpermissive]

template<> class std::iterator_traits<Token_ptr>{ 
public: 
    typedef Word difference_type; 
    typedef Word value_type; 
    typedef Token_ptr pointer; 
    typedef Word& reference ; 
    typedef std::bidirectional_iterator_tag iterator_category ; 
}; 

Mimo wszystko działa poprawnie, nie każdy organ wiedzieć, co dokładnie oznacza i dlaczego jest wydane ostrzeżenie. (g ++ wydaje ostrzeżenie, podczas gdy clang ++ nie).

+0

Wydaje się, że jest to ten sam problem, co zgłoszony w [to pytanie] (http://stackoverflow.com/questions/25311512/specialization-of-template-in-different-namespace). – nonsensickle

+0

[dlaczego specjalizacja szablonów nie może znajdować się w innym obszarze nazw] (http://stackoverflow.com/questions/3072248/why-arent-template-specializations-allowed-to-be-in-different-namespaces) również być przedmiotem zainteresowania. – nonsensickle

Odpowiedz

12

Zakładając, że są to w trybie kompilacji C++ 11 (od dzyń nie dał ostrzeżenie) i że ta specjalizacja jest w globalnej przestrzeni nazw, to nie ma nic złego w kodzie. Jest to błąd g ++. §14.7.3 [temp.expl.spec]/p2:

Wyraźna specjalizacja zgłasza się w otaczającej przestrzeni nazw wyspecjalizowane szablonu. Wyraźna specjalizacja, której identyfikator nie jest kwalifikowana, powinna być zadeklarowana w najbliższej otaczającej przestrzeni nazw szablonu lub, jeśli przestrzeń nazw jest wbudowana (7.3.1), dowolna przestrzeń nazw z jego otaczającego zestawu przestrzeni nazw. Taką deklaracją może być również deklaracja . Jeśli deklaracja nie jest definicją , specjalizacja może zostać zdefiniowana później (7.3.1.2).

Globalna przestrzeń nazw jest „namespace załączając specjalistycznego szablonu”, a declarator-id jest kwalifikowany z std::, więc zdanie drugie nie stosuje się. Aby obejść ten problem, możesz zrobić to, co sugeruje odpowiedź cdhowie - otwierając blok namespace std i umieszczając tam specjalizację.

Zobacz CWG issue 374 i GCC bug 56480.

+1

Jak denerwujące. Wygląda na to, że gcc nie naprawił go do wersji 7.0 – Justin

5

Jest tu jeden widoczny problem i jeden potencjalnie niewidoczny problem. Widoczny problem polega na tym, że ten kod nie znajduje się w bloku namespace std. Aby specjalizować szablon, musisz znajdować się w obszarze nazw szablonu, które specjalizujesz. Podanie nazwy przestrzeni nazw jako części typu faktycznie nie działa w tym przypadku. Więc trzeba to zrobić:

namespace std 
{ 
    template<> class iterator_traits<Token_ptr>{ 
    public: 
     typedef Word difference_type; 
     typedef Word value_type; 
     typedef Token_ptr pointer; 
     typedef Word& reference ; 
     typedef std::bidirectional_iterator_tag iterator_category ; 
    }; 
} 

Innym potencjalnym problemem jest to, że kod ten może być już wewnątrz innego namespace bloku (nie mogę powiedzieć, ponieważ nie jest to prawdopodobnie cały plik źródłowy). Jeśli tak, musisz najpierw zamknąć ten blok przestrzeni nazw, aby namespace std nie był zagnieżdżony w żadnych innych blokach przestrzeni nazw.

Dalsze czytanie: Specialization of 'template<class _Tp> struct std::less' in different namespace

Powiązane problemy