Frage

Ich bin derzeit das Hinzufügen einiger Funktionen unserer Logging-Bibliothek. Eines davon ist die Möglichkeit, einen Modul-Namen für eine Klasse zu deklarieren, das aus dieser Klasse schriftlich auf alle Log-Meldungen wird automatisch preprended. Wenn jedoch kein Modulname angegeben ist, wird nichts vorangestellt. Derzeit bin ich ein Charakterzug-Klasse, die eine statische Funktion, dass die Renditen der Name hat.

template< class T >
struct ModuleNameTrait {
    static std::string Value() { return ""; }
};

template< >
struct ModuleNameTrait< Foo > {
    static std::string Value() { return "Foo"; }
};

Diese Klasse kann definiert werden, um einen Helfer-Makro. Der Nachteil ist, dass der Modul-Name außerhalb der Klasse deklariert werden muss. Ich möchte dies in der Klasse möglich sein. Auch ich möchte in der Lage, alle Logging-Code unter Verwendung einer Präprozessordirektive zu entfernen. Ich weiß, dass man mit SFINAE können überprüfen, ob ein Template-Argumente ein bestimmtes Mitglied, aber da andere Menschen, die mit Vorlagen nicht so freundlich sind, wie ich bin, müssen Sie den Code halten, ich bin auf der Suche für eine viel einfachere Lösung. Wenn es keine gibt, werde ich dabei bleiben die Züge nähern.

Vielen Dank im Voraus!

War es hilfreich?

Lösung

  

Ich mag dies möglich innerhalb der Klasse sein.

Dies ist nicht möglich mit Ihrem Ansatz, explizite Spezialisierungen im Namensraum zu erklären haben, von denen die Vorlage ein Mitglied ist.

Sie müssen nicht sagen, wie die tatsächliche Verwendung von Code wie folgt aussehen, aber Sie sollen Namen und Überladungsauflösung für Sie arbeiten in der Lage zu lassen (zum Beispiel von einem Logging Makro):

template<class T> const char* const name(const T&) { return ""; }

class X;
const char* const name(const X&) { return "X"; }

struct X {
    // prints "X"
    void f() { std::cout << name(*this) <<  std::endl; }
};

struct Y {
    static const char* const name(const Y&) { return "Y"; }    
    // prints "Y"
    void f() { std::cout << name(*this) << std::endl; }
};

struct Z {
    // prints ""
    void f() { std::cout << name(*this) << std::endl; }
};

Wenn Sie name() nur in Klassen definieren wollen und nicht außerhalb, gibt es natürlich keine Notwendigkeit für Vorlagen oder Überlastungen:

const char* const name() { return ""; }

struct X {
    static const char* const name() { return "X"; }    
    // prints "X"
    void f() { std::cout << name() << std::endl; }
};

struct Y {
    // prints ""
    void f() { std::cout << name() <<  std::endl; }
};

Andere Tipps

Ich bin nicht sicher, wie einfach sollte die Lösung sein, hier ist ein sehr einfach ich ein paar Mal verwendet wird.

Es ist eine Basisklasse ClassName mit so etwas wie:

class ClassName
{
    string name;
public:
    ClassName( string strName = "" ) : name(strName)
    {
         if( strName.length() )
               strName += ": ";
    }
    string getName()
    {
        return name;
    }
};
#ifdef _DEBUG
    #define LOG cout << getName() 
#else
    #define LOG cout
#endif

Und andere Klasse wäre es erben, was seinen Namen:

class Session : virtual public ClassName
{
public:
    Session() : ClassName("Session")
    {
    }

    void func()
    {
         LOG << "Some log here" << endl;
    }
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top