Dove dovrebbero essere collocati i sovraccarichi degli operatori non membri?

Voglio sovraccaricare l’ operator<< per la mia class. Dovrei aggiungere questa definizione sovraccaricata allo spazio dei nomi std ? (dato che l’ ostream operator<< fa parte dello spazio dei nomi std ) O dovrei semplicemente lasciarlo nello spazio dei nomi globale?

In breve:

 class MyClass { }; namespace std { ostream& operator<< ( ostream& Ostr, const MyClass& MyType ) {} } 

O

 class MyClass { }; std::ostream& operator<< ( std::ostream& Ostr, const MyClass& MyType ) {} 

Quale è più appropriato e perché? Grazie in anticipo per le vostre risposte.

È necessario inserire il sovraccarico dell’operatore nello stesso spazio dei nomi della class.

Ciò consentirà di trovare l’operatore durante la risoluzione di sovraccarico utilizzando la ricerca dipendente dall’argomento (beh, in realtà, dal momento che ostream è nello std nomi, il sovraccarico verrà rilevato anche se lo si inserisce nello spazio dei nomi std , ma non c’è motivo di farlo quella).

Dal punto di vista delle buone pratiche di progettazione, il sovraccarico dell’operatore è più una parte dell’interfaccia della tua class che l’interfaccia di ostream , quindi appartiene allo stesso spazio dei nomi della class (vedi anche Namespace di Herb Sutter e il Principio di interfaccia ).

Dal punto di vista della scrittura di codice conforms agli standard e portatile, non si può mettere il sovraccarico dell’operatore nello spazio dei nomi std . Sebbene sia ansible aggiungere specializzazioni di modelli per quadro definite dall’utente allo std nomi, non è ansible aggiungere sovraccarichi di funzioni aggiuntivi.

Non aggiungerlo allo spazio dei nomi std , posizionarlo nello stesso spazio dei nomi della class. Lo scopo di uno spazio dei nomi è prevenire le collisioni. Lo standard dice

17.4.3.1 Nomi riservati

Non è definito per un programma C ++ l’aggiunta di dichiarazioni o definizioni allo spazio dei nomi std o namespace all’interno dello std del namespace, se non diversamente specificato. Un programma può aggiungere specializzazioni di modelli per qualsiasi modello di libreria standard allo std di namespace. Tale specializzazione (completa o parziale) di un modello di libreria standard risulta in un comportamento indefinito a meno che la dichiarazione non dipenda da un nome definito dall’utente di collegamento esterno e a meno che la specializzazione soddisfi i requisiti di libreria standard per il modello originale.

Non aggiungere allo spazio dei nomi standard. Motivo: se tutti lo facessero, lo spazio dei nomi standard avrebbe un mucchio di scontri tra nomi, il che vanifica lo scopo di uno spazio dei nomi.

Il tuo objective è che la tua class sia “ostream-able”. Non è necessario che sia nello spazio dei nomi standard per farlo. Finché è in qualunque namepsace è dichiarata la tua class, stai bene. Metterlo nello spazio dei nomi standard sarebbe una ctriggers pratica.