2013-04-09 11 views
1

Je suis en train d'écrire une bibliothèque de journal qui utiliserait un outil externedétection espace de noms

Pour rendre la bibliothèque plus utiliser naturelle, je voudrais être en mesure de détecter l'espace de noms dans lequel Cout est utilisé.

concrètement le résultat devrait être utilisé comme celui-ci

namespace A 
{ 
    void foo() 
    { 
      cout << "Something went very wrong" << endl; 
    } 
} 

namespace B 
{ 
    void bar() 
    { 
      cout << "C should equal 3" << endl; 
    } 
} 

int main() 
{ 
    B::bar(); 
    A::foo(); 
} 

et la sortie résultante devrait ressembler à ceci

MODULE::B : C should equal 3 
MODULE::A : Something went very wrong 

J'utilise déjà std::streambuf ajouter certains mots-clés à la sortie de Cout, i tous doit être capable de spécifier quel streambuf utiliser dans quel namespace.

Comment puis-je y parvenir?

La bibliothèque que je crée doit également être intégrée dans un projet avec plusieurs espaces de noms qui font un usage intensif de la déclaration using namespace. J'aurais besoin d'une solution qui ne nécessitera pas de supprimer ces déclarations.

edit1: Je ne me soucie pas d'avoir à spécifier manuellement l'espace de noms est associé à quelle chaîne ou en ajoutant des objets à l'un des espaces de noms utilisés (sauf std bien sûr)

+0

Le compilateur ne vous dit-il pas déjà que quelque chose ne va pas avec 'A :: bar()' et 'B :: foo()'? –

+0

Possible duplicate - http://stackoverflow.com/q/10657711/2065121 –

+0

@AndyProwl c'était une faute de frappe, merci de l'avoir remarqué – tiridactil

Répondre

2

Que diriez-vous de créer votre flux d'enregistreur personnalisé? De cette façon, l'utilisateur peut spécifier le composant qui a échoué, comme ceci:

namespace A { 
    void foo() 
    { 
      log("A") << "Something went very wrong" << endl; 
    } 
} 

namespace B { 
    void bar() 
    { 
      log("B") << "C should equal 3" << endl; 
    } 
} 

int main() 
{ 
    B::bar(); 
    A::foo(); 
} 

Peut-être moins automagique, mais __FILE__ macro pourrait également donner quelques informations.

+0

ajouter un enregistreur spécifique ferait exactement ce que j'essaye de réaliser mais a un défaut que j'essayais de contourner qui est que je devrais trouver et changer n'importe quel cout existant afin d'empêcher des notations sans modul – tiridactil

+1

'# defining'' cout' en quelque chose d'autre pourrait être la seule option alors. –

+1

Bien que je n'aime pas '# définir'' cout' comme une solution à long terme, vous pouvez l'utiliser pour en détecter les utilisations et vous pouvez supprimer le définir après l'avoir modifié pour votre journalisation particulière. –

1

Ce n'est pas possible dans la langue. Si vous utilisez Clang, vous pouvez recompiler Clang pour effectuer une telle tâche pour vous.

1

vous pouvez essayer d'injecter la fonction comme std::string namespace_name() dans chaque espace de noms que vous voulez afficher, et ensuite appeler std::cout << namespace_name() conduirait sortie espace de nom le plus intérieur

0

Je tente d'atteindre votre objectif. Mais cela dépend de GCC.

#include <cxxabi.h> 
#include <typeinfo> 
using namespace std; 

string retrive_name(const char *x) { 
    int status; 
    char *realname = abi::__cxa_demangle(x, 0, 0, &status); 
    string n = realname; 
    free(realname); 
    return n; 
} 

namespace A { 
struct Foo 
{ 
    static void foo() { 
     cout << retrive_name(typeid (Foo).name()) << endl; 
    } 
}; 
} 

namespace B { 
struct Bar 
{ 
    static void bar() { 
     cout << retrive_name(typeid (Bar).name()) << endl; 
    } 
}; 
} 

int main() { 
    A::Foo::foo(); 
    B::Bar::bar(); 
} 

Sortie

A::Foo 
B::Bar 

Cette réponse montre comment utiliser abi sous GCC pour demangle typeid(X).name(). Mais vous devriez utiliser des approches plus simples et plus lisibles.