2015-06-03 17 views
5

Ho cercato di creare alcuni overload dell'operatore (* e +) su una classe che è racchiusa in puntatori intelligenti.Sovraccarico dell'operatore di classe racchiuso tra puntatori intelligenti

auto p = std::make_unique<Polynomial<T>>(); 

Quando si tenta di sovraccaricarlo utilizzando il normale sovraccarico, richiede ovviamente i tipi di puntatore intelligente.

Modifica, quindi:

std::unique_ptr<Polynomial<T>> operator+(const std::unique_ptr<Polynomial<T>>& right); 

template<class T>std::unique_ptr<Polynomial<T>> Polynomial<T>::operator+(const std::unique_ptr<Polynomial<T>>& right) { 
    //Do stuff 
} 

E l'errore:

Error from trying to use the + operator

Quindi, come si fa a sovraccaricare gli operatori normali quando la classe è incapsulato in una smart pointer?

+1

"Quando cerco di sovraccaricarlo con una normale sovraccarico, si chiede, ovviamente, per i tipi di puntatore intelligente." -- Che cosa. – Shoe

+0

Perché queste classi sono racchiuse in puntatori intelligenti? Perché non puoi usarli come tipi di valore? –

risposta

11

No.

farli funzionare operazioni sui pointees, non sui puntatori:

*p = *p + *p 

Sarebbe molto confusa per gli utenti del codice, se improvvisamente puntatori avevano semantica completamente diversi e inaspettati.

Sarebbe anche confuso per voi.

2

So how do you go about overloading the normal operators when the class is encapsulated in a smartpointer?

Basta dichiarare come si farebbe normalmente:

template<typename T> 
Polynomial<T> operator*(Polynomial<T> lhs, Polynomial<T> rhs) { ... } 

template<typename T> 
Polynomial<T> operator+(Polynomial<T> lhs, Polynomial<T> rhs) { ... } 

e poi dato qualcosa come:

auto p = std::make_unique<Polynomial<int>>(); 
auto q = std::make_unique<Polynomial<int>>(); 

basta chiamare:

auto x = (*p) * (*q); 
auto y = (*q) + (*p); 

Live demo


L'errore ha fornito:

enter image description here

è dovuto al fatto che il vostro operatore di sovraccarico:

std::unique_ptr<Polynomial<T>> operator+(const std::unique_ptr<Polynomial<T>>& right); 

sta sovraccaricando il unariooperator+ per espressioni come +x.

E l'altro:

template<class T> 
std::unique_ptr<Polynomial<T>> Polynomial<T>::operator+(const std::unique_ptr<Polynomial<T>>& right) { 
    //Do stuff 
} 

sta sovraccaricando operator+ per operandi del tipo Polynomial<T> e std::unique_ptr<Polynomial<T>>.

Pertanto dato due unique_ptr<Polynomial<T>>, cioè x e y, la seguente espressione:

x + y 

non trova una risoluzione sovraccarico per operator+.

Inoltre, scoraggo molto l'overloading degli operatori per i tipi di libreria standard.

2

Per una risposta diretta alla tua domanda, sono d'accordo con @LightnessRacesinOrbit: Semplicemente non. Ma la ragione per scrivere un'altra risposta è che la domanda che mi stai facendo somiglia un po 'a XY-problem.

Hai una classe Polynomial<T> ma ti aspetti che l'utente lo copra in un puntatore intelligente? Questo è peschoso in quanto un progetto sano si aspetterebbe che l'utente possa lavorare direttamente con Polynomial, fornendo quindi operatori normali che lavorano direttamente su quel tipo.

Fai un passo indietro e pensa al motivo per cui pensi che un puntatore intelligente sarebbe usato/necessario/utile. Spesso, questo viene fatto per presunti motivi di efficienza, giusto? Ma questo significa solo che dovresti ripensare a come hai implementato lo stesso Polynomial. Guardare nel seguito:

  • Il Polynomial dispone di commutatore di movimento e -assegnazione? In caso contrario, implementalo.
  • E i dati memorizzati? Forse la memoria interna dovrebbe essere gestita da un puntatore intelligente. Insieme alla semantica del movimento, questo può portare a operazioni molto efficienti.
  • Per il sovraccarico dell'operatore, attuare a+=b;, utilizzare una libreria per generare a+b. Controllare Boost.Operators o il mio df.operators, quest'ultimo è anche sensibile al movimento.

Con la giusta applicazione, la voglia di utilizzare std::unique_ptr<Polynomial<T>> dovrebbe andare via :)

+0

'template friend Operatore polinomiale + (Lhs && lhs, Rhs && rhs) {Polynomial ret = std :: forward (lhs); ret + = std :: forward (rhs); return ret; } '- perché hai bisogno di una libreria per questo? Immagino che tu possa presumere commutatività e, in quel caso, usare condizionatamente a destra oa sinistra per il 'ret 'iniziale? E i test SFINAE, presumo. E alcuni funzionano per evitare conflittuali 'operatore + 'ambiguità. – Yakk

+0

@Yakk Alcune persone non sono d'accordo con il mio approccio, ma con sovraccarichi per i provvisori, è possibile ottimizzare ulteriormente restituendo un riferimento rval invece di un nuovo oggetto in alcuni casi. "Consapevole del movimento" significa più per me che la tua implementazione. Soprattutto per le classi in cui i provvisori aggiuntivi hanno un costo significativo e 'Polinomiale ' sembra esattamente come uno di quei casi. –

+1

Mai e poi mai restituire un riferimento rvalue (al di fuori delle espressioni cast): significa che l'estensione della durata di riferimento non funziona. Qualcosa di semplice come 'for (coeff x: a + b)' non funzionerà! E a che serve? – Yakk

Problemi correlati