2012-10-09 10 views
7

Ho una domanda per l'amicizia modello specifico in C++. nel libro C++ Primer, il modello specifico amicizia è scritto così:Amicizia modello specifico in C++

template <class T> class Foo3; 
template <class T> void templ_fcn3(const T&); 
template <class Type> class Bar { 
    // each instantiation of Bar grants access to the 
    // version of Foo3 or templ_fcn3 instantiated with the same type 
    friend class Foo3<Type>; 
    friend void templ_fcn3<Type>(const Type&); 
    // ... 
}; 

Il punto speciale è che non v'è

<Type> 

dopo il nome della classe o funzione nel amico dichiarazione.

Tuttavia, in pratica, se scrivo questo:

template <class Type> class T_CheckPointer; 
template <class T> T_CheckPointer<T> operator+(const T_CheckPointer<T> &, const size_t n); 

template <typename Type> 
class T_CheckPointer { 

    // Specific Template Friendship 
    friend T_CheckPointer<Type> 
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n); 

// other code... 

} 

Ci sarà un errore durante istanze per la funzione di modello.

E se cambio

// Specific Template Friendship 
friend T_CheckPointer<Type> 
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n); 

a

// Specific Template Friendship 
friend T_CheckPointer<Type> 
    operator+ <> (const T_CheckPointer<Type> &, const size_t n); 

cancellando la parola tipo dopo il nome della funzione, allora tutto sarà a posto.

Chiunque può dirmi il motivo?


Per informazioni, c'è il messaggio di errore di quando chiamo

int iarr[] = {1, 2, 3, 4}; 
T_CheckPointer<int> itcp(iarr, iarr+4); 

messaggio di errore:

/usr/include/c++/4.4/bits/stl_iterator_base_types.h: In instantiation of ‘std::iterator_traits<int>’: 
/usr/include/c++/4.4/bits/stl_iterator.h:96: instantiated from ‘std::reverse_iterator<int>’ 
../Classes/T_CheckPointer.hpp:31: instantiated from ‘T_CheckPointer<int>’ 
../PE16.cpp:520: instantiated from here 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:127: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:128: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:129: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:130: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:131: error: ‘int’ is not a class, struct, or union type 
+0

Qual è il messaggio di errore? – enobayram

+0

@enobayram, grazie per l'attenzione, li ho messi nell'articolo. – Tianyi

+0

Potresti fornire un ** esempio ** minimo (che viene compilato ad es.Ideone) che mostra il problema? E hai provato ad aggiornare a gcc 4.7? – TemplateRex

risposta

4

Ecco un esempio minimo:

template<typename T> struct U { typedef typename T::X X; }; 
template<typename T> void foo(typename U<T>::X); 

template<typename T> struct S; 
template<typename T> void foo(S<T>); 
template<typename T> struct S { friend void foo<T>(S<T>); }; 

template struct S<int>; 

Il motivo per cui la dichiarazione friend ha esito negativo è che fornendo un elenco completo degli argomenti del modello si richiede al compilatore di specializzarsi su tutti i modelli di funzione disponibili e scegliere quello che corrisponde meglio alla firma. La specializzazione della prima definizione di foo si traduce nella specializzazione di U con un argomento che si traduce in un programma mal formato.

Se invece si omette l'argomento del modello, verrà dedotto dagli argomenti. Come tale argomento template la deduzione viene eseguita in base a 14.8.2 [temp.deduct], e in particolare si applica 14.8.2p8, il che significa che l'errore di sostituzione nella specializzazione di U non è un errore (SFINAE).

Questa è una buona ragione per omettere gli argomenti del modello ovunque possano essere dedotti dal contesto (ad esempio, la funzione oi tipi di parametri dell'operatore). Si noti che è ancora necessario fornire le parentesi <> per garantire che il operator + venga letto come ID modello (14.5.4 [temp.friend]).

+0

+1 Questa è davvero una bella risposta! Si noti inoltre che le parentesi "<>" servono a impedire la selezione delle funzioni non template anziché delle funzioni template. Vedi questa vecchia colonna di Herb Sutter http://www.drdobbs.com/befriending-templates/184403853 – TemplateRex

+0

+1 Grazie mille per la tua risposta! La tua risposta è molto chiara. @ecatmur – Tianyi

Problemi correlati