2014-10-17 16 views
8

Questo esempio estremamente minimale non riuscirà a compilare perché A<int> non può accedere al membro privato i in A<double>Come consentire ad un metodo di accedere ai membri privati ​​di altre istanze di classi template?

template <class T> 
class A { 
    int i; 
    public: 
    template <class U> 
    void copy_i_from(const A<U> & a){ 
     i = a.i; 
    } 
}; 

int main(void) { 
    A<int> ai; 
    A<double> ad; 
    ai.copy_i_from(ad); 
    return 0; 
} 

so che posso fare tutte le istanze del modello amici gli uni degli altri (vedi: How to access private members of other template class instances?), ma dal momento che ho solo un metodo che richiede l'accesso (come nell'esempio) preferirei limitare l'amicizia a quel metodo. È possibile?

+1

Per il downvoter: mi piacerebbe sapere cosa posso fare per migliorare la domanda! – DarioP

+0

Entrambe le risposte e la domanda stessa sono state downvoted in silenzio; Sospetto che non abbia niente a che fare con il contenuto. – Angew

risposta

8

Si è possibile. Le funzioni membro possono essere designate normalmente come amici.

template <class T> 
class A { 
    int i; 
    public: 
    template <class U> 
    void copy_i_from(const A<U> & a){ 
     i = a.i; 
    } 
    template <class F> 
    template <class U> 
    friend void A<F>::copy_i_from(const A<U> & a); 
}; 

int main(void) { 
    A<int> ai; 
    A<double> ad; 
    ai.copy_i_from(ad); 
    return 0; 
} 

Live example (gcc one Ideone)


Si noti che a differenza di gcc, clang rejects the code. Non riesco a trovare nulla nello standard che lo renderebbe invalido, però.

+0

Questo è quello che ho provato, ma non funziona (non è il downvoter) – jrok

+0

@jrok Works per me (er, per Ideone GGC). – Angew

+0

@PiotrS. Allora perché non funziona senza la dichiarazione 'friend'? L'ho provato. – Angew

6

Sembra che se si vuole avere una funzione di membro amico, il seguente non funziona su clang:

template <class T> 
class A { 
    int i; 
    public: 
    template <class U> 
    void copy_i_from(const A<U> & a){ 
     i = a.i; 
    } 
    template <class F> 
    template <class U> friend void A<F>::copy_i_from(const A<U> & a); 
}; 

int main(void) { 
    A<int> ai; 
    A<double> ad; 
    ai.copy_i_from(ad); 
    return 0; 
} 

mentre it works on gcc.

Il problema sembra essere un problema di clang con la rappresentazione del modello di classe amico per il quale lo specificatore del nome dipendente non può essere risolto nell'AST: http://llvm.org/klaus/clang/commit/8b0fa5241a0416fc50dfbb7e38f20e777f191848/ (ancora nel trunk al momento della scrittura di questo).

Pertanto, è possibile utilizzare la versione della funzione membro precedente anche se potrebbe non funzionare su clang finché non viene risolto.

Una soluzione piano-B è quello di avere una funzione amico su modelli libera, anche se potrebbe non essere ciò che si vuole (accettata da entrambi cland e gcc):

#include <iostream> 
using namespace std; 

template <class T> 
class A { 
    int i; 
public: 
    template<class V, class U> 
    friend void copy_i_from(A<V>& t, const A<U> & a); 
}; 

template<class V, class U> 
void copy_i_from(A<V>& t, const A<U> & a){ 
    t.i = a.i; 
} 

int main(void) { 
    A<int> ai; 
    A<double> ad; 
    copy_i_from(ai,ad); 
    return 0; 
} 

Example

+1

Penso che questa sia stata una valida risposta anche prima della modifica (mi sono sentito male quando l'hai cancellato), ma ora è ancora meglio! – DarioP