2013-02-25 11 views
5

Mi scuso se il titolo di questa domanda è meno che utile; Io non conosco un modo succinto di fare questa domanda senza dare l'esempio seguente:Un argomento modello template da un altro spazio dei nomi può essere un amico?

template <template <class> class Arg> 
class C { 
    typedef C<Arg> type; 
    friend class Arg<type>; 
    public: 
    C() { 
     a_.set(this); 
    } 
    private: 
    int i_; 
    Arg<type> a_; 
}; 

template <class Type> 
class Arg1 { 
    public: 
    void set(Type* t) { 
     t_ = t; 
     t_->i_ = 1; 
    } 
    private: 
    Type* t_; 
}; 

namespace NS { 

    template <class Type> 
    class Arg2 { 
     public: 
     void set(Type* t) { 
      t_ = t; 
      t_->i_ = 2; 
     } 
     private: 
     Type* t_; 
    }; 

} 

Come si può vedere, Arg2 è una copia di Arg1. Tuttavia, VS 2008 consente solo Arg1 per essere usato come un argomento di un template:

int main() { 
    C<Arg1> c1; // compiles ok 
    C<NS::Arg2> c2; // error C2248 

    return 0; 
} 

L'errore è 'C<Arg>::i_' : cannot access private member declared in class 'C<Arg>'. Tutto funziona bene se i_ è reso pubblico, quindi questo sembra essere un problema di amicizia.

Che cosa causa la mancata riuscita della dichiarazione di amicizia quando l'argomento del modello di modello si trova in uno spazio dei nomi diverso?

+0

Dovrei aggiungere che lo stesso codice non riesce a compilare sia in VS 2010 che in VS 2012. –

risposta

0

L'appartenenza allo spazio dei nomi non influisce sull'idoneità per l'amicizia. Questo è un bug del compilatore.

friend e namespace sono funzionalità linguistiche che interagiscono, tuttavia, quindi non è particolarmente sorprendente come bug. Forse è in realtà una dichiarazione amichevole senza senso nello spazio dei nomi allegato, ::Arg2<type>.

+0

Dato gli altri commenti (ora cancellati) che indicano che clang e gcc compilano il mio esempio senza errori, sto pensando che questo sia corretto risposta. –