Funzioni autonome nello spazio dei nomi globale

4

Quando si scrivono funzioni non associate e libere, possono essere inserite nello spazio dei nomi globale fintanto che la firma specifica un oggetto con scope dello spazio dei nomi? Ad esempio, nel codice seguente, la progettazione accettabile per "Esempio 2"? Quale è meglio, Esempio 1 o Esempio 2? La tua risposta cambia se la funzione è un sovraccarico dell'operatore?

Ricerca: Non penso che questa domanda sia stata affrontata quando ho preso una classe di programmazione C ++ (o potrebbe essere stata affrontata prima che io fossi pronto a capirlo). Ho provato a cercare la risposta con alcune varianti diverse delle parole chiave, ma non ho ottenuto risultati di qualità.

#include <iostream>
#include <string>
#include <sstream>

/* Example 1 */
namespace myapp
{
    namespace xyz
    {
        class Thing
        {
        public:
            Thing( int value ) : myValue( value ) {}
            void setValue( int value ) { myValue = value; }
            int getValue() const { return myValue; }
        private:
            int myValue;
        };
        std::string toString( const Thing& thing )
        {
            std::stringstream ss;
            ss << thing.getValue();
            return ss.str();
        }
    }
}

/* Example 2 */
namespace myapp
{
    namespace xyz
    {
        class AnotherThing
        {
        public:
            AnotherThing( int value ) : myValue( value ) {}
            void setValue( int value ) { myValue = value; }
            int getValue() const { return myValue; }
        private:
            int myValue;
        };
    }
}
std::string toString( const myapp::xyz::AnotherThing& thing )
{
    std::stringstream ss;
    ss << thing.getValue();
    return ss.str();
}

int main(int argc, const char * argv[])
{
    /* Example 1 */
    myapp::xyz::Thing t( 1 );
    std::cout << myapp::xyz::toString( t ) << std::endl;

    /* Example 2 */
    myapp::xyz::AnotherThing a( 2 );
    std::cout << toString( a ) << std::endl;

    return 0;
}
    
posta Matthew James Briggs 24.02.2015 - 18:14
fonte

2 risposte

2

boost utilizza molte funzioni gratuite (le funzioni gratuite sono una buona cosa). Le funzioni gratuite sono mantenute vicino allo spazio dei nomi che coinvolge gli oggetti o altre classi correlate associate alla funzione libera. Quindi le definizioni delle funzioni libere vengono issate agli spazi dei nomi superiori come richiesto.

Questa tecnica dà il controllo sull'ambito delle funzioni libere. Le funzioni libere "Utility" possono essere definite in un namespace, quindi non vengono sollevate trattandole come funzioni "private-like".

In questo caso, l'Esempio 1 è una scelta più appropriata, ma l'aggiunta di dichiarazioni di sollevamento negli spazi dei nomi esterni consentirà alle funzioni di essere più facilmente referenziate.

    
risposta data 24.02.2015 - 21:35
fonte
3

Metti la funzione nello stesso spazio dei nomi delle classi su cui opera.

In questo modo, non ingombra il namespace globale ed è correttamente raggruppato per una facile comprensione, ma sarà facilmente trovato da ADL (argument-dependent-lookup).

Per inciso, questo è il modo in cui swap dovrebbe essere implementato e utilizzato:
Lo standard fornisce il generico std::swap e varie varianti specializzate nello spazio dei nomi degli oggetti su cui opera, e dipende dal set di overload costituito dalla versione generica, e qualunque sia trovato da ADL dando quello giusto.

    
risposta data 24.02.2015 - 21:43
fonte

Leggi altre domande sui tag